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

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

ただいまの
回答率

90.53%

  • Swift

    7210questions

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

Decodableを利用したJSONデータのパースに関して

受付中

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 125

takataka1

score 1

JSONレスポンスは下になります。

{
  "info": {
    "photo_num": ###,
    "photo": [
      {
        "photo_id": ###,
        "user_id": ###,
        "album_id": ###,
        "photo_title": "タイトル",
        "favorite_num": ###,
        "comment_num": ###,
        "view_num": ###,
        "copyright": "normal/creativecommons",
        "copyright_commercial": "yes/no"
        "copyright_modifications": "yes/no/share"
        "original_height": ##,
        "original_width": ###,
        "geo": {
            "latitude": ###,
            "longitude": ###
        },
        "date": "YYYY-MM-DD",
        "regist_time": "YYYY-MM-DDThh:mm:ss+09:00",
        "url": "URL",
        "image_url": "URL",
        "original_image_url": "URL",
        "thumbnail_image_url": "URL",
        "large_tag": "<a href=\"...\">...</a>",
        "medium_tag": "<a href=\"...\">...</a>"
      },
      ...
    ]
  }
}

上の中にある"image_url"を取り出したく下のようにコードを記載しました

  Alamofire.request(url, method: .get, parameters: params, encoding: URLEncoding.default, headers: nil).responseData { (dataResponse) in

            if let err = dataResponse.error{
                print("failed to contact photos", err)
                return
            }

            guard let data = dataResponse.data else {return}

            do{
                let searchResult = try JSONDecoder().decode(SearchResults.self, from: data)
                self.photos = searchResult.info.photo!
                self.collectionView.reloadData()

            }catch let decodeErr{
                print("failed to decode:", decodeErr)
            }
        }

 struct SearchResults: Decodable {

        struct Photo: Decodable{
            let photo_num: Int?
            let photo: [Photos]?
        }
        let info: Photo
    }

class Photos: Decodable{
    var image_url: String?
    var original_image_url: String?
}

しかし以下のようなエラーメッセージが出ます。

failed to decode: keyNotFound(CodingKeys(stringValue: "info", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"info\", intValue: nil) (\"info\").", underlyingError: nil))
failed to decode: keyNotFound(CodingKeys(stringValue: "info", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"info\", intValue: nil) (\"info\").", underlyingError: nil))
failed to decode: keyNotFound(CodingKeys(stringValue: "info", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"info\", intValue: nil) (\"info\").", underlyingError: nil))

どなたか対処法をご教示いただけないでしょうか。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • fuzzball

    2018/07/23 13:56

    Decodableを使わないとダメなんでしょうか?

    キャンセル

回答 1

0

とりあえずPlaygroundで動く状態に書いてみました、試してみてください。

import Foundation

extension KeyedDecodingContainer {
    func decode<ResultType: Decodable>(forKey key: Key, defaultValue: ResultType) -> ResultType {
        return (try? decode(ResultType.self, forKey: key)) ?? defaultValue
    }
}

var data = """
{
  "info": {
    "photo_num": "abc",
    "photo": [
      {
        "photo_id": "",
        "user_id": "",
        "album_id": "",
        "photo_title": "タイトル",
        "favorite_num": "",
        "comment_num": "",
        "view_num": "",
        "copyright": "normal/creativecommons",
        "copyright_commercial": "yes/no",
        "copyright_modifications": "yes/no/share",
        "original_height": "",
        "original_width": "",
        "geo": {
          "latitude": "",
          "longitude": ""
        },
        "date": "YYYY-MM-DD",
        "regist_time": "YYYY-MM-DDThh:mm:ss+09:00",
        "url": "URL",
        "image_url": "URL - image_url",
        "original_image_url": "URL - original_image_url",
        "thumbnail_image_url": "URL",
        "large_tag": "<a href=\\\"...\\\">...</a>",
        "medium_tag": "<a href=\\\"...\\\">...</a>"
      }
    ]
  }
}
""".data(using: .utf8)

// \u{22}

struct SearchResults: Codable {
    let info: Photos
}

struct Photos: Codable {
    let photo_num: String
    let photo: [Photo]
}

struct Photo: Codable {

    let photoId: String
    let userId: String
    let albumId: String
    let photoTitle: String
    let favoriteNum: String
    let commentNum: String
    let viewNum: String
    let copyright: String
    let copyrightCommercial: String
    let copyrightModifications: String
    let originalHeight: String
    let originalWidth: String
    let geo: Geo
    let date: String
    let registTime: String
    let url: String
    let imageUrl: String
    let originalImageUrl: String
    let thumbnailImageUrl: String
    let largeTag: String
    let mediumTag: String

    enum CodingKeys: String, CodingKey {

        case photoId = "photo_id"
        case userId = "user_id"
        case albumId = "album_id"
        case photoTitle = "photo_title"
        case favoriteNum = "favorite_num"
        case commentNum = "comment_num"
        case viewNum = "view_num"
        case copyright
        case copyrightCommercial = "copyright_commercial"
        case copyrightModifications = "copyright_modifications"
        case originalHeight = "original_height"
        case originalWidth = "original_width"
        case geo
        case date
        case registTime = "regist_time"
        case url
        case imageUrl = "image_url"
        case originalImageUrl = "original_image_url"
        case thumbnailImageUrl = "thumbnail_image_url"
        case largeTag = "large_tag"
        case mediumTag = "medium_tag"
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        photoId = container.decode(forKey: .photoId, defaultValue: "")
        userId = container.decode(forKey: .userId, defaultValue: "")
        albumId = container.decode(forKey: .albumId, defaultValue: "")
        photoTitle =  container.decode(forKey: .photoTitle, defaultValue: "")
        favoriteNum  =  container.decode(forKey: .favoriteNum, defaultValue: "")
        commentNum = container.decode(forKey: .commentNum, defaultValue: "")
        viewNum = container.decode(forKey: .viewNum, defaultValue: "")
        copyright = container.decode(forKey: .copyright, defaultValue: "")
        copyrightCommercial = container.decode(forKey: .copyrightCommercial, defaultValue: "")
        copyrightModifications = container.decode(forKey: .copyrightModifications, defaultValue: "")
        originalHeight = container.decode(forKey: .originalHeight, defaultValue: "")
        originalWidth = container.decode(forKey: .originalWidth, defaultValue: "")
        geo = try container.decode(Geo.self, forKey: .geo)
        date = container.decode(forKey: .date, defaultValue: "")
        registTime = container.decode(forKey: .registTime, defaultValue: "")
        url = container.decode(forKey: .url, defaultValue: "")
        imageUrl = container.decode(forKey: .imageUrl, defaultValue: "")
        originalImageUrl = container.decode(forKey: .originalImageUrl, defaultValue: "")
        thumbnailImageUrl = container.decode(forKey: .thumbnailImageUrl, defaultValue: "")
        largeTag = container.decode(forKey: .largeTag, defaultValue: "")
        mediumTag = container.decode(forKey: .mediumTag, defaultValue: "")
    }
}

struct Geo: Codable {
    let latitude: String
    let longitude: String
}



// Decode
let searchResult = try? JSONDecoder().decode(SearchResults.self, from: data!)
if let searchResult = searchResult {

    print(searchResult.info.photo.first?.imageUrl)
    //=> Optional("URL - image_url")
    print(searchResult.info.photo.first?.originalImageUrl)
    //=> Optional("URL - original_image_url")
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.53%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Swift

    7210questions

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