Swift 4 Decodable协议如何处理包含名称直到运行时才知道的键的字典?例如:
[ { "categoryName": "Trending", "Trending": [ { "category": "Trending", "trailerPrice": "", "isFavourit": null, "isWatchlist": null } ] }, { "categoryName": "Comedy", "Comedy": [ { "category": "Comedy", "trailerPrice": "", "isFavourit": null, "isWatchlist": null } ] } ]
在这里,我们有一系列的字典。第一个具有键categoryName和Trending,而第二个具有键categoryName和Comedy。categoryName键的值告诉我第二个键的名称。如何使用Decodable来表达呢?
categoryName
Trending
Comedy
关键在于如何定义CodingKeys属性。虽然最常见的情况是enum它可以是符合CodingKey协议的任何内容。要创建动态键,可以调用静态函数:
CodingKeys
enum
CodingKey
struct Category: Decodable { struct Detail: Decodable { var category: String var trailerPrice: String var isFavorite: Bool? var isWatchlist: Bool? } var name: String var detail: Detail private struct CodingKeys: CodingKey { var intValue: Int? var stringValue: String init?(intValue: Int) { self.intValue = intValue; self.stringValue = "\(intValue)" } init?(stringValue: String) { self.stringValue = stringValue } static let name = CodingKeys.make(key: "categoryName") static func make(key: String) -> CodingKeys { return CodingKeys(stringValue: key)! } } init(from coder: Decoder) throws { let container = try coder.container(keyedBy: CodingKeys.self) self.name = try container.decode(String.self, forKey: .name) self.detail = try container.decode([Detail].self, forKey: .make(key: name)).first! } }
用法:
let jsonData = """ [ { "categoryName": "Trending", "Trending": [ { "category": "Trending", "trailerPrice": "", "isFavourite": null, "isWatchlist": null } ] }, { "categoryName": "Comedy", "Comedy": [ { "category": "Comedy", "trailerPrice": "", "isFavourite": null, "isWatchlist": null } ] } ] """.data(using: .utf8)! let categories = try! JSONDecoder().decode([Category].self, from: jsonData)
(我isFavourit将JSON 更改为,isFavourite因为我认为这是拼写错误。如果不是这种情况,则很容易修改代码)
isFavourit
isFavourite