🍎

JSONEncoder、JSONDecoderを理解していこう!

2021/11/14に公開

最近仕事でJSONEncoder、JSONDecoderを使ったんですが、ふわっと理解で終わっていたので、せっかくならまとめてしまおうと思い作成しました。

JSONEncoder、JSONDecoderとは?

● JSONEncoder

JSONEncoder(Apple公式ドキュメント)には、「データ型のインスタンスをJSONオブジェクトとしてエンコードするオブジェクトです。」 と書かれています。

● JSONDecoder

JSONDecoder(Apple公式ドキュメント)には、「JSONオブジェクトからデータタイプのインスタンスをデコードするオブジェクトです。」 と書かれています。

どんな時に使う?(+前提知識)

では、どんな時にこの2つの機能を使うのか解説していきます。
まず、前提知識として Codable についても説明しておきます。
Swift4からCodableという機能が追加され、JSONなどの文字列を容易に任意のオブジェクトに変換できるようになりました。便利ですね!
それ以前は SwiftyJSONなどを使って、変換する必要がありました。
もう少し詳しく解説すると、CodableはEncodable(エンコード)とDecodable(デコード)から成ります。
式に表すと、
Codable = Encodable + Decodable となります。こちらの用語も以下で解説します!

●エンコード:データベースなどから、ネットワークを介して送信されたデータをプログラムで使用する前に、適切な形式に変換すること。
一言でいうと、データを他の形式へ変換することです。
●デコード:エンコードされたデータを元の形式へ戻す(変換する)こと。
一言でいうと、エンコードされたデータを元の形式へ戻すことです。

使い方

一般的にアプリケーションがAPIを通じてサーバーと通信する場合、JSONを形式でやり取りすることがメジャーだと思います。JSONEncode、JSONDecoderはその過程で活用できます。
では実際にユーザーのデータ(JSON)をJSONEncoder、JSONDecoderで扱ってみましょう!

1.JSONEncodeの使い方

今回はUserというデータ型を想定して確認してみます。

1.

初めに、structでUserというデータ型を作成し、そこにそれぞれid,namee,mailという定数を定義します。
実際のプロジェクトではclassで定義することが多いと思いますが、今回はstructの方で検証します。
この際、気をつけて欲しいのはデータ型を定義する際にCodableで実装することです。

struct User:Codable {
    let id:String
    let name:String
    let email:String
    let address:String
}

2.

次に実際にJSONEncoderを使用する、class(今回はSampleClassとします)を作成します。

class SampleClass {
    let user = User(id:"1",name:"Ichiro",email: "ichiro@sample.com",address: "Tokyo")
    let encoder = JSONEncoder()
    
    func encodeJason(){
        do {
            let data = try encoder.encode(user)
            let jsonstr:String = String(data: data, encoding: .utf8)!
            print(jsonstr)
        } catch {
            print("error")
        }
    }
}

今回はuserという定数を作成し、(id:"1",name:"Taro",email: "sample.com")をいうデータを入れ、このデータをJsonに変換していきます。
encoderという定数でJSONEncoder()を定義します。これによって、JSONEncoder()が使用できるようになりました!
あとはデータを整形するクラス(encodeJason)を作り、下記のようにStringをJsonに変換します。

実際に想定されるJsonは下記のような感じです。
※今回はid,名前,メールアドレス,住所を想定しています。あくまでも検証用なので、とてもシンプルに書いていますが、実プロジェクトではもっと複雑且つデータ量も多いJsonデータがほとんどだと思います。

{
    "id":1,
    "name":"Ichiro",
    "email":"ichiro@sample.com",
    "address":"Tokyo"
}

下記が今解説した全体コードです。

//全体のコード
import UIKit

struct User:Codable {
    let id:String
    let name:String
    let email:String
}

class SampleClass {
    let user = User(id:"1",name:"Taro",email: "sample.com")
    let encoder = JSONEncoder()
    
    func encodeJason(){
        do {
            let data = try encoder.encode(user)
            let jsonString:String = String(data: data, encoding: .utf8)!
            print(jsonString)
        } catch {
            print("error")
        }
    }
}

SampleClass().encodeJason()

4.

今回はXcode Playgroundで確認します。
下記画像の結果の様に、Stringで定義したユーザーデータがエンコードされJsonとして表示されました!
JSONEncoderを使えば、この様に簡単にJsonにデータをエンコードすることができます!

2.JSONDecoderの使い方

Decoder同様、Userというデータ型を想定するため、上記で定義したUserというデータ型をそのまま使用します。
こちらもEncoder同様データ型を定義する際にCodableで実装することが重要です。

1.

まずはデコードする、実際のJsonデータを用意する必要がります。
下記の様に、想定されるJsonデータをjsonStringに定義します。これは2.で定義するclass内で定義します。

let jsonString = """
    {
    "id":1,
    "name":"Ichiro",
    "email":"ichiro@sample.com",
    "address":"Tokyo"
    }
    """

2.

次に実際にJSONDecoderを使用する、class(今回もSampleClassとします)を作成します。

class SampleClass {
    let jsonString = """
    {
    "id":1,
    "name":"Ichiro",
    "email":"ichiro@sample.com",
    "address":"Tokyo"
    }
    """
    let decoder: JSONDecoder = JSONDecoder()
    
    func decodeJason(){
        decoder.dateDecodingStrategy = .iso8601
        do {
            let decodeData: User = try decoder.decode(User.self, from: jsonString.data(using: .utf8)!)
            print(decodeData)
        } catch {
            print("error")
        }
    }

こちらではデコードですので、jsonStringというJsonデータをStringに変換していきます。
decoderという定数でJSONDecoder()を定義します。これによって、JSONDecoder()が使用できるようになりました!
データを整形するクラス(decodeJason)を作り、定数decodeDataでJsonをStringに変換します。

下記がデコード処理の全体コードです。

//全体のコード
import UIKit

struct User:Codable {
    let id:Int
    let name:String
    let email:String
    let address:String
}

class SampleClass {
    let jsonString = """
    {
    "id":1,
    "name":"Ichiro",
    "email":"ichiro@sample.com",
    "address":"Tokyo"
    }
    """
    let decoder: JSONDecoder = JSONDecoder()
    
    func decodeJason(){
        decoder.dateDecodingStrategy = .iso8601
        do {
            let decodeData: User = try decoder.decode(User.self, from: jsonString.data(using: .utf8)!)
            print(decodeData)
        } catch {
            print("error")
        }
    }
}

SampleClass().decodeJason()

4.

こちらもXcode Playgroundで確認します。
下記画像の結果の様に、Jsonとして定義したユーザーデータがStringにデコードされて表示されました!
JSONDecoderを使えば、この様に簡単にJsonデータをデコードすることができます!

まとめ

簡単にですが、JSONEncoder、JSONDecoderについて書いてみました!
ポイントをまとめると、
●JSONEncoderはデータ型のインスタンスをJSONオブジェクトとしてエンコードするオブジェクト
●JSONDecoderはJSONオブジェクトからデータタイプのインスタンスをデコードするオブジェクト
●classやstructの方でデータ定義する際、Codableで実装する
となります!
今回は基礎的な部分についてまとめました。皆さんのJSONEncoder、JSONDecoderに対する理解の助けとなったら幸いです。
読んでいただき、ありがとうございました!

参考記事

・Codableについて備忘録
https://qiita.com/s_emoto/items/deda5abcb0adc2217e86
・Swiftの初め方 - エンコードとデコード
https://swift.codelly.dev/guide/ネットワーク/エンコードとデコード.html#data型
・SwiftでJSONを読込・書出しする方法
https://medium.com/@bj1024/swift4-codable-json-encode-17eaa95372d1

Discussion