🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

2782閲覧

SWIFT 入れ子のあるJSONファイルの読み方

seastar

総合スコア62

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

1クリップ

投稿2021/03/11 15:19

Swiftでjsonファイルを読んでいますが、複雑な階層のjsonファイルの読み方がわからないため、ご教示お願いいたします。
jsonは出力されるもので自分で作っていないため、整形せずそのまま使う前提でお願いします。

JSONファイルサンプル

1{ 2 "キー1":"値1", 3 "キー2":{"キー3":"値3","キー4":[4-1,4-2]}, 4 "キー5":{"キー6":"値6","キー7":"値7","キー8":"値8"} 5}, 6上記のまとまりが数十データあるイメージです。 7~~~

以下、キー1は参考サイトから値の取得ができました。
キー2の値の取得の書き方が分かりません。

Swift

1~~省略~~ 2 guard let url = Bundle.main.url(forResource: "23", withExtension: "json") else { 3 return 4 } 5 6 guard let data = try? Data(contentsOf: url) else { 7 return 8 } 9 10 let deco_line = JSONDecoder() 11 guard let value = try? deco_line.decode([Data].self, from: data) else { 12 return 13 } 14 15 label1.text = value.キー1 ←取得できた。 16 label2.text = value.キー2の中のキー3の値 ⇦これを取得できるようにしたい。 17~~省略~~ 18 19struct Data: Codable { 20 var キー1: String 21 var キー2: ?? 22 var キー5: ?? 23}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

今回のような JSON オブジェクトが入れ子になった構造を Codable で扱うときは、それぞれの JSON 型 を意識して、それごとに分けて型を定義すると考えるとわかりやすいかもしれません。

挙げてくださった JSON を少し直す必要がありそうでしたので、次のように直しますけれど、これについて考えていきます。

json

1[ 2 { 3 "キー1":"値1", 4 "キー2":{"キー3":"値3","キー4":["値4−1","値4−2"]}, 5 "キー5":{"キー6":"値6","キー7":"値7","キー8":"値8"} 6 }, 7]
[Data] 型
  1. まず、いちばん外側は JSON の配列型 になっています。
  2. 配列オブジェクトの中には JSON のオブジェクト型 になっています。

ここまでは、既に質問で挙げられている通り、内側の JSON オブジェクト型 を独自に定義した Data 型 で表現していて、それの配列なので [Data] 型 で扱っています。

Data 型

このような要領で、次のように Data 型 の内容を考えていきます。

  1. キー1の値は JSON の文字列型 になっています。
  2. キー2の値は、JSON オブジェクト型 になっています。
  3. キー5の値は、JSON オブジェクト型 になっています。

ここで キー1 の値の JSON の文字列型 は Swift の String 型 で表現できるので、残りの キー2 の値と キー5 の値のそれぞれを表現していきます。これらはそれぞれ JSON オブジェクト型 なので、それらを表現できる型をさらに定義してみます。

キー2型

まず、キー2 の値をピックアップすると、次のようになっています。

json

1{"キー3":"値3","キー4":["値4−1","値4−2"]}

これは JSON オブジェクト型 で、次の2つのキーと値の組み合わせを持っています。

  1. キー3 ⋯ JSON 文字列型 の値
  2. キー4 ⋯ JSON 配列型 の値

このとき キー4 は、内容が全て文字列型の配列なので、これは [String] 型で表現できます。
つまり、ここでは既存の型を使って次のように、この JSON オブジェクト を表現できる型が作れます。

swift

1struct キー2型 : Codable { 2 3 var キー3: String 4 var キー4: [String] 5}

この型で キー2 の値を表現できました。

キー5型

続いて キー5 についても考えてみます。

今回の場合は キー5 の値は JSON オブジェクト型 ですけれど、それが扱う値は全て文字列型なので [String : String] 型を使って表現できます。これは Codable に対応しているので、これをそのまま使ってもいいですし、先ほどの キー2 と同じ要領で独自の型を追加定義することも可能です。

独自の型を追加定義する場合は、先ほどのように値を切り出してみると考えやすくなります。

json

1{"キー6":"値6","キー7":"値7","キー8":"値8"}

これを順番に整理すると⋯

  1. キー6の値は JSON 文字列型 です。
  2. キー7の値は JSON 文字列型 です。
  3. キー8の値は JSON 文字列型 です。

これを型で表現すると、次のようにかけます。

swift

1struct キー5型 : Codable { 2 3 var キー6: String 4 var キー7: String 5 var キー8: String 6}

このようにとてもシンプルな構造なので、慣れないうちは先にこちらを理解してから、改めて キー2型 がなんでそうなるかを考えると理解できると思います。

Data 型を完成させる

このようにして、各キーの値を Swift の型で表現できるようになったら、さらにこれまでと同じ要領で Data 型を定義することができます。

swift

1struct Data : Codable { 2 3 var キー1: String 4 var キー2: キー2型 5 var キー5: キー5型 6}

これで、今回の課題の JSON 文字列を読み込めるようになったと思います。

試してみてください。

投稿2021/03/11 17:26

編集2021/03/11 18:49
TomohiroKumagai

総合スコア441

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TsukubaDepot

2021/03/12 03:29

JSONの仕組みを理解した上で、 https://app.quicktype.io/ などのようなツールも併用するといいかもしれませんね。 逆にいうと、上記のようなツールを使っても、失敗するときは失敗するので、JSONやCodableの原理は理解しておいて損はないと思います。
seastar

2021/03/13 10:27

TomohiroKumagai様、回答ありがとうございます。 1つずつ考える、この考え方、要領で解決することができました。 struct Data: Codable { let type: Type let geometry: Geometry? } struct Geometry: Codable { let type: GeometryType let list: [Double] } 迅速に回答いただ他にも関わらず反応が遅く失礼しました。
seastar

2021/03/13 10:29

TsukubaDepot様 いつもありがとうございます。 便利なサイトですね、知りませんでした。 これ使わせてもらいました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問