2017-10-18 6 views
0

URLから取得している大きなJSON Stringを解析しようとしています。私がテストに使用していますJSONは以下の通りです:SwiftでDecodableとCodingKeysを使用してJSONを解析する4

let json = """ 
{ 
"feed": { 
    "title": "Harry Potter", 
    "test": "I dont want this value", 
    "results": [ 
     { 
     "author": "JK Rowling", 
     "artworkURL": "A url", 
     "genres": [ 
      { 
       "name": "Fantasy" 
      }, 
      { 
       "name": "Scifi" 
      } 
     ], 
      "name": "Goblet of Fire", 
      "releaseDate": "2000-07-08" 
     }, 
     { 
     "author": "JK Rowling", 
     "artworkURL": "A url", 
     "genres": [ 
      { 
       "name": "Fantasy" 
      }, 
      { 
       "name": "Scifi" 
      } 
      ], 
      "name": "Half Blood Prince", 
      "releaseDate": "2009-07-15" 
      } 
     ] 
    } 
} 
""".data(using: .utf8)! 

私はにデータを配置するために、結合データの構造体を持っている:

struct Genre: Decodable { 
    let name: String 
} 

struct Book: Decodable { 
    let author: String 
    let artworkURL: URL 
    let genres: [Genre] 
    let name: String 
    let releaseDate: String 
} 

struct BookCollection { 
    let title: String 
    let books: [Book] 

    enum CodingKeys: String, CodingKey { 
     case feed 
    } 

    enum FeedKeys: String, CodingKey { 
     case title, results 
    } 

    enum ResultKeys: String, CodingKey { 
     case author, artworkURL, genres, name, releaseDate 
    } 

    enum GenreKeys: String, CodingKey { 
     case name 
    } 
} 

extension BookCollection: Decodable { 
    init(from decoder: Decoder) throws { 
     let values = try decoder.container(keyedBy: CodingKeys.self) 

     let feed = try values.nestedContainer(keyedBy: FeedKeys.self, 
    forKey: .feed) 
     self.title = try feed.decode(String.self, forKey: .title) 
     self.books = try feed.decode([Track].self, forKey: .results) 
    } 
} 

私はそのようにのような情報をオフに印刷しています:

do { 
    let response = try JSONDecoder().decode(BookCollection.self, from: json) 
    for book in response.books { 
     print(book.genres) 
    } 
} catch { 
    print(error) 
} 

ジャンル以外の情報をすべて印刷しても問題ありません。これは私にのジャンルの配列を与えますが、私は book.genres.name という名前にアクセスすることはできません。私は使用する必要があります: book.genres[0] そしてそれは私にちょうど最初のインデックスの結果を与えます。

私のBookCollection拡張でJSONのデコードを完璧にする方法がありますか?book.genres.nameを利用しますか?

はあなたが本当にその余分nameプロパティが必要な場合は、新しい拡張機能で行うことができますあなたの

+0

'book.genres.name'のどの値が返されるべきですか? –

+0

@PauloMattos各ブックの配列を返す必要があります。最初の本の場合、それは 'ファンタジー'と 'サイフィー'でしょう。 –

+0

@DominicPillaあなたはブック構造体 '拡張子帳に読み取り専用の計算プロパティを追加することができます{ のvar allGenres:[文字列] { 戻りgenres.map {$ 0.name}} }'と '使うプリント(book.allGenres ) ' –

答えて

1

ありがとう:

extension Array where Element == Genre { 
    var name: [String] { 
     return self.map { $0.name } 
    } 
} 

これはそこにすべての[Genre]値に前述のnameプロパティを追加し、あなたのBookタイプで定義されたものも含めて。その拡張子を対応するswiftファイルで利用可能なものよりもprivateと宣言した場合、それが本当にあなたの後であることを確認してください。

+0

恐ろしい!それはうまくいった。しかし、私のBookCollectionエクステンション内でこれを行う方法がないことを確認するには?私はそのエクステンションの外でこれを追加しました。 –

+0

@DominicPillaいいえ、それはできません。 )あなたの目標を達成するために '[Genre]'を実際に拡張する必要があります; –

+0

私はそれぞれのデータ構造体に対して 'extensions'を作ろうとしましたが、成功しませんでした。正しく実装されていればうまくいくと言っていますか? –

0

多くのenum codingKeysを使用して型を手動でデコードする必要性を排除するために、データ構造を変更してJSON構造形式をマップできます。以下のコードでは、構造体をネストする必要はないことに注意してください。並列に配置することもできます。このコードはエンコードされたJSONデータでテストされています

public struct HarryPotterFeed: Codable { 
    public let feed: BookCollection 

    public struct BookCollection: Codable { 
    public let title: String 
    public let books: [Book] 

    // map properties books to json's "results" 
    enum CodingKeys: String, CodingKey { 
     case title // needs to come along 
     case books = "results" 
    } 

    public struct Book: Codable { 
     public let author, name, artworkURL, releaseDate : String 
     public let genres: [Genre] 

     public struct Genre: Codable { 
     public let name: String 
     } 
    } 
    } 
} 

// Decode JSON 

do { 
    let response = try JSONDecoder().decode(HarryPotterFeed.self, from: json) 
    for book in response.feed.books { 
    for name in book.genres { 
     print(name) 
    } 
    } 
} catch { 
    print("PROBLEM DECODING JSON \(error)") 
} 
+0

あなたのコメントをありがとうございます。 JSONのデータ構造には、必要ではない複数のキーがあり、データ構造を無駄な値で埋めることになりました。 –

関連する問題