我需要解码像这样的字典:
{
"Bob": "London",
"Alice": "Berlin"
...
}
进入 Person
结构数组:
struct Person {
let name: String
let city: String
}
我想使用 Coding
协议(protocol)实现这个映射,但很难将每个键用作结构的值。
Q: What about
NSJsonSerialization
?A: I know it's quite trivial with
NSJsonSerialization
, but implementing it withDecodable
protocol was bugging me a bit :)
最佳答案
更多的想法提醒我,在这种情况下我不需要 AnyCodingKey,因为这是一个非常简单的结构。解码为[String: String]
,然后进行映射:
struct PersonList: Decodable {
let persons: [Person]
init(from decoder: Decoder) throws {
self.persons = try decoder.singleValueContainer()
.decode([String: String].self)
.map(Person.init)
}
}
let list = try JSONDecoder().decode(PersonList.self, from: json).persons
// [Person(name: "Bob", city: "London"), Person(name: "Alice", city: "Berlin")]
旧答案,因为有时这种技术很方便。
这方面的关键工具是经常需要的 CodingKey(它确实应该在 stdlib 中),AnyCodingKey:
struct AnyCodingKey: CodingKey {
var stringValue: String = ""
init?(stringValue: String) { self.stringValue = stringValue }
var intValue: Int?
init?(intValue: Int) { self.intValue = intValue }
}
有了它,您只需要一个容器来悬挂解码器。称它为 PersonList:
struct PersonList: Decodable {
let persons: [Person]
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: AnyCodingKey.self)
self.persons = try container.allKeys.map { key in
Person(name: key.stringValue,
city: try container.decode(String.self, forKey: key))
}
}
}
let list = try JSONDecoder().decode(PersonList.self, from: json).persons
// [Person(name: "Bob", city: "London"), Person(name: "Alice", city: "Berlin")]
这只是将每个键/值映射到一个人。
请记住,JSON 对象是无序的,因此生成的数组可能与 JSON 的顺序不同,如本例所示。这无法通过 Foundation(JSONSerialization 或 JSONDecoder)修复;如果需要,您必须使用不同的 JSON 解析器。
关于ios - 如何在 Swift 中将字典解码为以键为值的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59019897/