この記事で紹介するコードはSwift5、iOS13で動かした時の物です。
JSONをパースする時にはCodableを継承したStructを作ります。
以下のような感じ。
struct Rest:Codable { let name:String }
例えば、{"name":"hoge"}
のJSONが与えられた時には以下のコードでパースできます。
let decoder = JSONDecoder() let json = try decoder.decode(Rest.self, from: data)
上記の例は、JSONの”name”がString型で返ってくることが確定している場合は問題がありませんが、JSON内の要素の型が時々変わるもの場合にはエラーが出ます。
以下の例を見てみよう。
struct Rest:Codable { budget:Int }
budgetの値がIntで返ってくる時もあればStringで返ってくることがある。
例えば、{"budget":3000}
or {"budget":""}
のケース。
Stringが返ってきた場合には上記の構造体ではパースした時にエラーが出る。
このようなイレギュラーなケースに対応するためは、手動でDecode処理を実装する必要がある。
Codableを継承している場合、Decodeはinit内で行う。
CodingKeys
にキー名を羅列し、キー名を指定してデコードする。
以下の実装例を見てみよう。
struct Rest:Codable { let budget:Int private enum CodingKeys : String, CodingKey { case budget } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let budgetInt = try? container.decode(Int.self, forKey: .budget) let budgetString = try? container.decode(String.self, forKey: .budget) // Intでデコードできなかった場合には0を代入する。 self.budget = budgetInt ?? (budgetString == "" ? 0 : 0) } }
- `CondingKeys`にbudgetを追加。
- budgetをInt型とString型の両方でデコードする。
- Int型でデコードできた場合にはそのまま代入、できなかった場合には0を代入する。
こんな感じ。
終わり。