iOS Decodableの基本的な使い方
English version below
はじめに
今回はSwift4 で追加されたDecodableの使い方について紹介します。
Decodableとは
API Requestなどで返ってくるJSONのData型を任意のクラスや構造体に変換する際に便利です。
これまではSwiftyJSONなどライブラリーを使ってJSONの構造体にアクセスすることが多かったと思います。
しかし、そのままSwiftyJSONを使う場合、
など、もやもやが僕の中にはありました。
Decodableを使うことで決まったJSONを決まったクラス/構造体にしか変換しないので、とてもわかりやすくて好きです。
Decodableを使って見る
構造体に対してDecodableのProtocolを適用する。
struct SomeStruct: Decodable { var value: String var version: Int enum CodingKeys: String, CodingKey { case value case version = "app_version" } }
試しにデコードして見る
let json: Data = """ { "value": "GoodString", "app_version": 5 } """.data(using: .utf8)! let someStruct = try? JSONDecoder().decode(SomeStruct.self, from: json)
詳細
構造体に対して、Decodableの適用を宣言。
CodingKeysという列挙体を宣言すると完了です。
CodingKeysはrawValueがStringの列挙体で、JSONの各Keyがどの変数に対応しているのかを宣言します。
CodingKeysのrawValueが変数名と等しい場合は、変数名をそのまま列挙体でも使用、異なる場合はrawValueに対してKey名を対応させます。
構造体の各変数はvarで宣言しないと、Decodeに失敗しnilが返ってきます。
JSONのKeyで存在の有無がOptionalの場合は構造体の変数宣言をOptionalにすればOKです。
struct SomeStruct: Decodable { var value: String var version: Int var exception: Int? enum CodingKeys: String, CodingKey { case value case version = "app_version" } }
階層のあるJSONをデコードする
次に、階層構造のあるJSONについてです。 上記のSomeStruct の中にInnerStructが配列で存在すること場合、次のように宣言します。
Decodableの宣言
struct SomeStruct: Decodable { var value: String var version: Int var inners: [InnerStruct] enum CodingKeys: String, CodingKey { case value case version = "app_version" case inners = "inner_structs" } } struct InnerStruct: Decodable { var index: Int var name: String enum CodingKeys: String, CodingKey { case index = "inner_index" case name = "inner_name" } }
今回はInnerStructは配列ですが、InnerStruct単体であれば[]を外せばOKです。
デコードする
let json: Data = """ { "value": "GoodString", "app_version": 5, "inner_structs": [{ "inner_index": 1, "inner_name": "myName" }] } """.data(using: .utf8)! let someStruct = try? JSONDecoder().decode(SomeStruct.self, from: json)
おわりに
とても便利です。簡単です。使っていきましょう。