楽天トラベルAPUを使ったAPIリクエストでdecodeに失敗しています。使用言語はswiftです。
おそらく,hotelキーの中が配列になっており、配列の0つ目にhotelBasicInfo,1つ目にhotelRatingInfoが当てられている箇所が原因だと思われます。
自分のコードでは、let hotel: [HotelInfo]
としていますが、同じ型が配列にまとめられているわけではないため、配列の1つ目であるhotelRatingInfoを見に行ったときにエラーが出てしまいます。
ワークアラウンドとしてlet info: HotelValue
の箇所をlet info: HotelValue?
とおいて、nullを許可すれば大丈夫だったのですが、何かすっきりしないやり方です。
他の方法を思いついた方がいればぜひご教授お願いしたいです。
swift側でのCodableの定義
swift
1struct Hotels: Codable { 2 let hotels: [Hotel] 3} 4 5struct Hotel: Codable { 6 let hotel: [HotelInfo] 7 8 struct HotelInfo: Codable { 9 let info: HotelValue 10 private enum CodingKeys: String, CodingKey { 11 case info = "hotelBasicInfo" 12 } 13 } 14} 15 16struct HotelValue: Codable { 17 let name: String 18 let infoURL: String 19 let description: String 20 let hotelImageURL: String 21 let roomImageURL: String 22 23 private enum CodingKeys: String, CodingKey { 24 case name = "hotelName" 25 case infoURL = "hotelInformationUrl" 26 case description = "hotelSpecial" 27 case hotelImageURL = "hotelImageUrl" 28 case roomImageURL = "roomImageUrl" 29 } 30}
レスポンスのjson
{ "pagingInfo": { "recordCount": 2309, "pageCount": 77, "page": 1, "first": 1, "last": 30 }, "hotels": [ { "hotel": [ { "hotelBasicInfo": { "hotelNo": 1019, "hotelName": "森のスパリゾート 北海道ホテル", "hotelInformationUrl": "https://img.travel.rakuten.co.jp/image/tr/api/kw/JBe8h/?f_no=1019", "planListUrl": "https://img.travel.rakuten.co.jp/image/tr/api/kw/3VTwt/?f_no=1019&f_flg=PLAN", "dpPlanListUrl": "https://img.travel.rakuten.co.jp/image/tr/api/kw/IWrzP/?noTomariHotel=1019", "reviewUrl": "https://img.travel.rakuten.co.jp/image/tr/api/kw/HTX0u/?f_hotel_no=1019", "hotelKanaName": "もりのすぱりじーと ほっかいどう", "hotelSpecial": "モール温泉浴場を備えた緑に囲まれたシティホテル。全室Wi-fi接続&LANケーブル接続可能", "hotelMinCharge": 3780, "latitude": 154468.78, "longitude": 515524.06, "postalCode": "080-0017", "address1": "北海道", "address2": "帯広市西7条南19丁目1", "telephoneNo": "0155-21-0001", "faxNo": "0155-25-3721", "access": "根室本線JR帯広駅南口から車で5分。帯広空港より車で30分。", "parkingInformation": "有り 180台 無料", "nearestStation": "帯広", "hotelImageUrl": "https://img.travel.rakuten.co.jp/share/HOTEL/1019/1019.jpg", "hotelThumbnailUrl": "https://img.travel.rakuten.co.jp/HIMG/90/1019.jpg", "roomImageUrl": "https://img.travel.rakuten.co.jp/share/HOTEL/1019/1019_tw1.jpg", "roomThumbnailUrl": "https://img.travel.rakuten.co.jp/HIMG/INTERIOR/1019.jpg", "hotelMapImageUrl": "https://img.travel.rakuten.co.jp/share/HOTEL/1019/1019map.gif", "reviewCount": 1876, "reviewAverage": 4.43, "userReview": "今回が2回目の宿泊ですが、今回は家族での利用のため、前回よりも広いテラス付きのツインにしました。朝にテラスから庭にいるリスが見れて家族もテンションが上がっていました。朝食も大変美味しく、大浴場も街中の… 2021-10-02 19:54:40投稿 <a href="https://img.travel.rakuten.co.jp/image/tr/api/kw/HTX0u/?f_hotel_no=1019" class="3click">つづきはこちら</a>" } }, { "hotelRatingInfo": { "serviceAverage": 4.27, "locationAverage": 4.29, "roomAverage": 4.39, "equipmentAverage": 4.32, "bathAverage": 4.26, "mealAverage": 4.42 } } ] }, { "hotel": [ { "hotelBasicInfo": { "hotelNo": 1968, "hotelName": "北海道第一ホテルサッポロ", "hotelInformationUrl": "https://img.travel.rakuten.co.jp/image/tr/api/kw/JBe8h/?f_no=1968", "planListUrl": "https://img.travel.rakuten.co.jp/image/tr/api/kw/3VTwt/?f_no=1968&f_flg=PLAN", "dpPlanListUrl": "https://img.travel.rakuten.co.jp/image/tr/api/kw/IWrzP/?noTomariHotel=1968", "reviewUrl": "https://img.travel.rakuten.co.jp/image/tr/api/kw/HTX0u/?f_hotel_no=1968", "hotelKanaName": "ほっかいどう だいいちほてる さっぽろ", "hotelSpecial": "コンビニ隣、飲食店街すぐそば。地下鉄駅、空港連絡バス乗り場まで徒歩1分。", "hotelMinCharge": 2250, "latitude": 155113.74, "longitude": 508850.83, "postalCode": "001-0023", "address1": "北海道", "address2": "札幌市北区北23条西4丁目2-6", "telephoneNo": "011-726-3232", "faxNo": "011-726-9855", "access": "JR札幌駅より地下鉄南北線麻生方面 「北24条駅」下車 → 4番出口徒歩1分。【高速】札樽道 → 北インターから約8分", "parkingInformation": "徒歩2,3分の契約駐車場(高さ2.1mまで)1泊900円", "nearestStation": "北24条", "hotelImageUrl": "https://img.travel.rakuten.co.jp/share/HOTEL/1968/1968.jpg", "hotelThumbnailUrl": "https://img.travel.rakuten.co.jp/HIMG/90/1968.jpg", "roomImageUrl": "https://img.travel.rakuten.co.jp/share/HOTEL/1968/1968_sgl.jpg", "roomThumbnailUrl": "https://img.travel.rakuten.co.jp/HIMG/INTERIOR/1968.jpg", "hotelMapImageUrl": "https://img.travel.rakuten.co.jp/share/HOTEL/1968/1968map.gif", "reviewCount": 1135, "reviewAverage": 3.63, "userReview": null } }, { "hotelRatingInfo": { "serviceAverage": 0, "locationAverage": 0, "roomAverage": 0, "equipmentAverage": 0, "bathAverage": 0, "mealAverage": 0 } } ] }, { "hotel": [ { "hotelBasicInfo": { "hotelNo": 68236, "hotelName": "北海道の輝き☆ティンクナ", "hotelInformationUrl": "https://img.travel.rakuten.co.jp/image/tr/api/kw/JBe8h/?f_no=68236", "planListUrl": "https://img.travel.rakuten.co.jp/image/tr/api/kw/3VTwt/?f_no=68236&f_flg=PLAN", "dpPlanListUrl": "https://img.travel.rakuten.co.jp/image/tr/api/kw/IWrzP/?noTomariHotel=68236", "reviewUrl": "https://img.travel.rakuten.co.jp/image/tr/api/kw/HTX0u/?f_hotel_no=68236", "hotelKanaName": "ほっかいどうのかがやき☆てぃんくな", "hotelSpecial": "阿蘇×北海道の創作フレンチが自慢。北海道から移住した夫婦が営む宿", "hotelMinCharge": 5780, "latitude": 118208.44, "longitude": 471872.92, "postalCode": "869-1504", "address1": "熊本県", "address2": "阿蘇郡南阿蘇村大字一関1471-2", "telephoneNo": "0967-62-8044", "faxNo": "0967-62-8166", "access": "阿蘇くまもと空港より車で約50分 ※ナビはGoogleマップをご利用ください。", "parkingInformation": "有り 8台 無料 予約不要", "nearestStation": "立野(熊本)", "hotelImageUrl": "https://img.travel.rakuten.co.jp/share/HOTEL/68236/68236.jpg", "hotelThumbnailUrl": "https://img.travel.rakuten.co.jp/HIMG/90/68236.jpg", "roomImageUrl": "https://img.travel.rakuten.co.jp/share/HOTEL/68236/68236_h.jpg", "roomThumbnailUrl": "https://img.travel.rakuten.co.jp/HIMG/INTERIOR/68236.jpg", "hotelMapImageUrl": "https://img.travel.rakuten.co.jp/share/HOTEL/68236/68236map.gif", "reviewCount": 229, "reviewAverage": 4.57, "userReview": null } }, { "hotelRatingInfo": { "serviceAverage": 0, "locationAverage": 0, "roomAverage": 0, "equipmentAverage": 0, "bathAverage": 0, "mealAverage": 0 } } ] } ] }
元の JSON の構造を素直に反映するなら let info: HotelValue? でしょうね。
(info の取得は、hotels 配列の 0 番目に info があるはずと決め打ちするのは美しくないので、hotels.first { $0.info != nil }?.info かなぁ。)
あなたの回答
tips
プレビュー