質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
Swift

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

Q&A

解決済

1回答

1290閲覧

Swift JSONDecoder()にてネストしたJSONデータを取得したい。

ataru2222

総合スコア272

Swift

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

0グッド

0クリップ

投稿2022/06/28 13:20

実現したいこと

Swift JSONDecoder()にてネストしたJSONデータを取得したい。

発生している問題・エラーメッセージ

こちらのサイトを参考に
https://qiita.com/kaba/items/6b5d7a1dc29831c6b36f

ネストしたJSONデータを取得して、構造体Flickrの中に格納したいのですが、下記のコードではnilになってしまいます。

print(jsonObject) のところでnilになる
その前の行のdataでpo dataを打つと何かのデータが取れております。

該当のソースコード

Swift

1 2struct Flickr: Decodable { 3 var server: String 4 var id: String 5 var secret: String 6 var owner: String 7 var title: String 8 9 } 10 11 12 override func viewDidLoad() { 13 super.viewDidLoad() 14 15 16 let baseURL = "https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=7f722a8b5deabe99d5dc7f50cfc6c364&text=cat&sort=interestingness-desc&per_page=12&license=4&extras=owner_name%2Clicense&format=json&nojsoncallback=1" 17 18 19 20 21 request(url: baseURL) 22} 23 24func request(url: String) { 25 AF.request(url, method: .get) 26 .responseJSON{(respons) in switch respons.result { 27 28 29 //データの取得に成功した場合 30 case .success: 31 32 guard let data = respons.data else { 33 return 34 } 35 36 let jsonObject = try? JSONDecoder().decode([Flickr].self, from: data) 37 print(jsonObject) 38 39 case .failure(_): 40 print(".failureブロックに入りました") 41 self.strAPIpath = "errorURL" 42 } 43 } 44 }

試したこと

複数のサイトを見ながら、打ち込んでみたのですが、こちらのURLの先がネスト状態というものなのか?
そこらへんから経験不足でよくわからず、困っております。

JSONデータURL
https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=7f722a8b5deabe99d5dc7f50cfc6c364&text=cat&sort=interestingness-desc&per_page=12&license=4&extras=owner_name%2Clicense&format=json&nojsoncallback=1

件数の項目があるのでこちらを配列形式のように取得したいのですが、こちらのサイトでJSONデータを正しく取得するにはどのように書いたら良いでしょうか?
詳しい方いらっしゃいましたらご教授ください。
宜しくお願いいたします。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答1

0

ベストアンサー

レスポンスのJSONは次のような形になるみたいです。

json

1{ 2 "photos": { 3 "page": 1, 4 "pages": 27797, 5 "perpage": 12, 6 "total": 333553, 7 "photo": [ 8 { 9 "id": "32019326474", 10 "owner": "133835212@N03", 11 "secret": "fa171d3364", 12 "server": "2418", 13 "farm": 3, 14 "title": "Mon 'tit p\\u00e8re aux aguets!", 15 "ispublic": 1, 16 "isfriend": 0, 17 "isfamily": 0, 18 "license": "4", 19 "ownername": "@ S@ndrine" 20 }, 21 // 省略

レスポンスに合わせてstructを作ると良いと思います。

swift

1struct Flickr: Decodable { 2 var photos: Photos 3 struct Photos: Decodable { 4 var page: Int 5 var pages: Int 6 var perpage: Int 7 var total: Int 8 var photo: [Photo] 9 struct Photo: Decodable { 10 var id: String 11 var owner: String 12 var secret: String 13 var server: String 14 var farm: Int 15 var title: String 16 // 省略 17 } 18 } 19}

jsonObject?.photos.photoの配列が欲しいデータになるでしょうか。

投稿2022/06/28 14:08

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

hoshi-takanori

2022/06/28 15:11

型をネストさせる必要はありません。
退会済みユーザー

退会済みユーザー

2022/06/28 15:54

hoshi-takanori様 コメントありがとうございます。 Section 1 Create a Landmark Model Step 6 https://developer.apple.com/tutorials/swiftui/building-lists-and-navigation (ちょっと前に認識したことですが)Swiftでは型も入れ子に記述するのが一般的なのかなと思ってそれに合わせて記述してみました。 *個人的には外から参照するのに入れ子になっているのは読みづらい印象なのですが、実際のところ一般的にはどうなのでしょうか・・? *業務でSwiftを扱ったことがないので・・すみません・・
ataru2222

2022/06/29 10:21

xg63ex2b様 回答していただきありがとうございます。 こちらのstructに変更してみたのですが、 jsonObjectを格納して表示する部分で print(jsonObject?.photos.photo)を入力するとエラーとなってしまします。 エラー内容はこちらで Value of type '[ViewController.Flickr]?' has no member 'photos' (タイプ'[ViewController.Flickr]?'の値 メンバーがいない'写真') structを変更しただけでprint(jsonObject)は通るもnilとなってしまします。 こちらについて解消法お分かりになりますでしょうか?
退会済みユーザー

退会済みユーザー

2022/06/29 10:25

すみません、デコードの部分は回答欄に記載していなかったですね・・ レスポンスの一番外側は配列ではなくてオブジェクトの形式ですので、 デコードに渡す型も配列ではない型を渡すと良いと思います。 `let jsonObject = try? JSONDecoder().decode([Flickr].self, from: data)` ↓↓↓↓↓↓↓↓↓↓ `let jsonObject = try? JSONDecoder().decode(Flickr.self, from: data)`
ataru2222

2022/06/29 10:33

できました!! 自分の実力外の部分で調べても調べても答えに辿り着けなくて本当に困っておりました。 復習して、次に活かせるようまとめておきます。 本当に本当にありがとうございました(涙)
hoshi-takanori

2022/07/02 02:55

お返事が遅くてごめんなさい。(昔は回答のコメントも通知が来たのに、リニューアル後は来なくなったような…。) > *個人的には外から参照するのに入れ子になっているのは読みづらい印象なのですが、実際のところ一般的にはどうなのでしょうか・・? 型を入れ子にすると、その型を使いたい時に Photo じゃなくて Flickr.Photos.Photo と書く必要があって面倒ですし、Photo を別のところでも使いたい場合にややこしいことになります。(でも、Photo という名前は一般的すぎるので、FlickrPhoto とかにしたくなるかも。) 逆に、特定の型に従属する型 (例えば、Photo の種類を enum で表したいとか) なら、入れ子にした方がいいかも知れません。(そういう意味では、Photos は入れ子でもいいのかも。)
退会済みユーザー

退会済みユーザー

2022/07/03 09:52

hoshi-takanori 様 コメントありがとうございます。 回答のコメントの返信は通知がないですね・・ > 型を入れ子にすると、その型を使いたい時に Photo じゃなくて Flickr.Photos.Photo と書く必要があって面倒ですし、Photo を別のところでも使いたい場合にややこしいことになります。 そうですよね。 C#とかですと、次のような規則もあるみたいでした。 > 入れ子にされた型とは、別の型のスコープ内で宣言された型のことです。 入れ子にされた型は、それを入れ子にする型のプライベート実装の詳細をカプセル化するときに便利です。 このような用途なので、入れ子にされた型は外部から参照できないようにします。 > https://docs.microsoft.com/ja-jp/dotnet/fundamentals/code-analysis/quality-rules/ca1034
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問