JSONのパース
APIから得られたJSONは文字列です。文字列のJSONをプログラムから利用できるように意味のあるオブジェクトに変換することをパースといいます。ここではJSONパースする方法について学びましょう。
JSONの構造を解析する
JSONをパースする前に、まずJSON自体の構造を確認しておきましょう。ブラウザからアクセスしたJSONの表示は次のとおりです。
JSONの構造は次のように考えられます。
最上位ブロックの中の「hits」内に各素材情報が並んでいる構造です。サンプルでは素材情報ではユニークな「id」と 大きい画像のURLである 「largeImageURL」のみを利用しますので、上記の図にはこの2つのプロパティのみを記載しています。
上記JSONをオブジェクトして解析するには、次のような2つの構造体で解析できます。
各プロパティを持つ構造体をそれぞれ次のようにContentView.swift 内に定義します。
// JSON全体を格納する構造体 struct SearchImageDataModel:Codable{ let total: Int let totalHits: Int let hits : [ImageData] } // 素材情報を格納す構造体 struct ImageData: Identifiable, Codable { let id: Int let largeImageURL: String }
JSONを解析するための構造体は、Codableプロトコルを継承して定義します。
JSONの各項目をそのままの名前で、String, Intの型に応じて定義します。各素材情報はここで定義したImageData構造体で扱いますので、項目「hits」は ImageData構造体の配列で定義します。
配列は要素を「[ ]」で囲うことで定義できます。「[ImageData]」と記述することで、ImageData構造体の配列であると定義します。
この定義の仕方は先の図のとおりです。
ImageData構造体は1つ1つ違いますので、Identifiableプロトコルを継承してJSON内の項目を区別できるようにします。JSON内の素材情報でユニークな id が存在しますので、今回はUUIDメソッドは利用せずに解析した id の値を使うようにしています。
JSONをパースして結果を確認する
JSONを解析するための構造体を定義した後は、実際にJSONをパースして結果を確認してみましょう。
JSONをパースするためには、JSONDecoder構造体のdecoded メソッドを利用します。
https://developer.apple.com/documentation/foundation/jsondecoder/2895189-decode
JSONDecoder構造体のdecoded メソッドの書式は次のとおりです。
パース後のオブジェクト = try? JSONDecoder().decode(JSONをパースする構造体.self, from: Dataオブジェクト)
JSONをパースする際にエラーが発生するかもしれないので try をつけます。さらにエラーなくパースできた場合も、パースした結果がないこともあるのでオプショナル型で結果が戻るように「?」をつけて利用します。結果は if let 文で受け取ります。
サンプルのJSONをパースする処理は次のように書けます。
if let decoded = try? JSONDecoder().decode(SearchImageDataModel.self, from: data) { print(decoded) }
URLSession構造体 の dataメソッド の戻り値である Dataオブジェクト を JSONDecoder構造体 のdecoded メソッドでパースします。JSONをパースする構造体は SearchImageDataModel構造体 です。decoded メソッドには、「JSONをパースする構造体」として SearchImageDataModel構造体 を引数に指定するため、「SearchImageDataModel.self」の書式で記述します。
インスタンスではなく、構造体自身を指す「.self」を忘れないようにしてください。
パース結果はif let文で 変数「decoded」に格納しています。
シミュレーターを起動してアプリを実行してボタンを押すと、コンソールに次のようにJSONのパーう結果を出力します。
解析結果として SearchImageDataModelオブジェクトを出力し、その中の hitsプロパティ に配列として ImageDataオブジェクト が並んでいることがわかります。それぞれのプロパティの値もここで確認できます。
サンプルコードを次のように編集して、ItemData構造体 の id と largeImageURL を参照すると次のように出力されます。
if let decoded = try? JSONDecoder().decode(SearchImageDataModel.self, from: data) { for item in decoded.hits { print(item.id) print(item.largeImageURL) print("-------") } }
JSONから ItemData構造体 の id と largeImageURL を取り出せていることが確認できます。
他の章に比べて一回の処理で複数の技術を利用する処理が目立ちますが、JSONを解析する流れは実感できたと思います。
9章、10章では8章のJSONの処理をさらに実践的にした処理を説明します。