実現したいこと
JSONの取得をし、検索結果を一覧表示できるようにしたい。
発生している問題・分からないこと
デバッグの方でguard let items = json.item else { ... }のブロックで「アイテムが見つかりませんでした」と出力されてしまいます。おそらく、そのためResultJson(item: nil)とJSONデータが帰ってきてしまってるんだと考えています。しかし、どのように修正すべきか分からないです、、、
どうかご教示よろしくお願いいたします。
該当のソースコード
Swift
1import SwiftUI 2 3//Identifiableプロトコルを利用して、お店情報をまとめる構造体 4struct OmiseItem : Identifiable { 5 let id = UUID() 6 let name: String 7 let link: URL 8 let image: URL 9} 10 11//お店データ検索用クラス 12@Observable class OmiseData { 13 //JSONのデータ構造 14 struct ResultJson: Codable { 15 //JSONのitem内のデータ構造 16 struct Item: Codable { 17 //お店の名称 18 let name : String? 19 //掲載URL 20 let url: URL? 21 //画像URL 22 let image: URL? 23 } 24 //複数要素 25 let item: [Item]? 26 }//ResultJson ここまで 27 28 //お店のリスト(Identifiableのプロトコル) 29 var omiseList: [OmiseItem] = [] 30 //クリックされたWebページのURL情報 31 var omiseLink: URL? 32 33 //web API検索用メソッド 第一引数:keyword 検索したいワード 34 func searchOmise(keyword: String) { 35 //デバッグエリアに出力 36 print("searchメソッドで受け取った値:\(keyword)") 37 38 //Taskは非同期で処理を実行できる 39 Task { 40 //ここから先は非同期で処理される 41 //非同期でお菓子を検索する 42 await search(keyword: keyword) 43 }//Taskここまで 44 }//searchOmiseここまで 45 46 //非同期でお店データを取得 47 //@MainActorを使いメインスレッドを更新する 48 @MainActor 49 private func search(keyword: String) async { 50 // お店の検索キーワードをURLエンコードする 51 guard let keyword_encode = keyword.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { 52 print("URLエンコードに失敗しました") 53 return 54 } 55 56 // リクエストURLの組み立て 57 guard let req_url = URL(string: "https://webservice.recruit.co.jp/hotpepper/gourmet/v1/?key=[APIキー取得済みです]&format=json&keyword=\(keyword_encode)&order=1") else { 58 print("リクエストURLの組み立てに失敗しました") 59 return 60 } 61 // デバッグエリアに出力 62 print(req_url) 63 64 do { 65 // リクエストURLからダウンロード 66 let (data, response) = try await URLSession.shared.data(from: req_url) 67 68 // responseがHTTPURLResponse型にキャストできるか確認 69 if let httpResponse = response as? HTTPURLResponse { 70 // HTTPレスポンスステータスコードやレスポンスヘッダーの確認 71 print("HTTPステータスコード: \(httpResponse.statusCode)") 72 print("HTTPヘッダー: \(httpResponse.allHeaderFields)") 73 } 74 75 // 取得したJSONデータを文字列として出力 76 if let jsonString = String(data: data, encoding: .utf8) { 77 print("取得したJSONデータ: \(jsonString)") 78 } 79 80 // JSONDecoderのインスタンスを取得 81 let decoder = JSONDecoder() 82 83 // JSONのパースを別のdo-catchで行う 84 do { 85 let json = try decoder.decode(ResultJson.self, from: data) 86 print("パース成功: \(json)") 87 88 // お店の情報が獲得できているか確認 89 guard let items = json.item else { 90 print("アイテムが見つかりませんでした") 91 return 92 } 93 // お店のリストを初期化 94 omiseList.removeAll() 95 96 // 取得しているお店の数だけ処理 97 for item in items { 98 // お店の名称、掲載URL、画像URLをアンラップ 99 if let name = item.name, 100 let link = item.url, 101 let image = item.image { 102 // 一つのお店を構造体でまとめて管理 103 let omise = OmiseItem(name: name, link: link, image: image) 104 // お店の配列へ追加 105 omiseList.append(omise) 106 } 107 } 108 print(omiseList) 109 } catch { 110 // JSONデコードのエラーをキャッチ 111 print("デコードエラー: \(error)") 112 } 113 114 } catch { 115 print("エラーが出ました") 116 } // do ここまで 117 } // search ここまで 118} 119
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
responseがHTTPURLResponse型にキャストできるか確認すると、HTTPステータスコード: 200と出力されているのでレスポンスヘッダーが正しく取得されていると思います。
補足
修正しました(2回目)
回答1件
あなたの回答
tips
プレビュー