问题描述
Swift 4 Decodable协议如何处理包含名称直到运行时才知道的键的字典?例如:
How does the Swift 4 Decodable protocol cope with a dictionary containing a key whose name is not known until runtime? For example:
[
{
"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来表达这一点?
Here we have an array of dictionaries; the first has keys categoryName
and Trending
, while the second has keys categoryName
and Comedy
. The value of the categoryName
key tells me the name of the second key. How do I express that using Decodable?
推荐答案
关键在于如何定义CodingKeys
属性.尽管最常见的是enum
,它可以是符合CodingKey
协议的任何内容.要创建动态键,您可以调用静态函数:
The key is in how you define the CodingKeys
property. While it's most commonly an enum
it can be anything that conforms to the CodingKey
protocol. And to make dynamic keys, you can call a static function:
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)
(由于我认为这是拼写错误,所以将JSON中的isFavourit
更改为isFavourite
.如果不是这样,很容易修改代码)
(I changed isFavourit
in the JSON to isFavourite
since I thought it was a mispelling. It's easy enough to adapt the code if that's not the case)
这篇关于Swift 4可解码,直到解码时才知道密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!