将 JSON 嵌套到带有 swift 的嵌套字典中
Nested JSON into nested dictionary with swift
我使用新的 Codable 协议将结构转换为 JSON,然后转换为字典以用于测试目的。问题是结构中的字典变量没有被转换回来并保持 Any
而不是 [Int: String]
struct Person: Codable {
var name: String?
var history: [Int: String]
init() {
self.name = "Name"
history = [0: "Test"]
}
}
let person = Person()
let jsonData = try JSONEncoder().encode(person)
let result = try JSONSerialization.jsonObject(with: jsonData, options: [])
let dictionary = result as? [String: Any]
print(dictionary)
这给了我以下结果
Optional(["history": {
0 = Test;
}, "name": Name])
我希望什么时候
Optional(["history":[0: "Test"]], "name": "Test"])
我将不胜感激关于为什么会发生这种情况的任何解释,或者更好的是,如何基本上进行深度 JSON 序列化的解决方案。
我正在添加一个 playground 来演示这个问题:
https://www.dropbox.com/s/igpntk7az0hevze/JSONSerialisation.playground.zip
正如您使用JSONEncoder
编码一样,您也可以使用JSONDecoder
解码json数据。在这种情况下,history
是一个不是默认类型之一的字典,因此添加带有自定义的 init(from decoder: Decoder)
将是获得预期字典的一种解决方法。
struct Person: Codable {
var name: String
var history: [Int: String]
init() {
self.name = "Name"
history = [0: "Test"]
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decodeIfPresent(String.self, forKey: .name) ?? "Failed to decode name"
self.history = try container.decodeIfPresent([Int: String].self, forKey: .history) ?? [-1: "Failed to decode history"]
}
}
let person = Person()
do {
let jsonData = try JSONEncoder().encode(person)
if let result = try? JSONDecoder().decode(Person.self, from: jsonData) {
print(result)
}
} catch {
print(error.localizedDescription)
}
原来它是一本字典,只是打印出来就好像它不是字典一样。我认为它不是字典的原因是调用
let history = dictionary["history"] as? [Int: String]
会导致 nil,但原因是 JSON 显然无法处理 [Int: String]
。相反,我的 [Int: String]
已经(可能是通过 JSONSerialization.jsonObject(with: jsonData, options: [])
函数)变成了 [String: Any]
.
let history = dictionary["history"] as? [String: String]
工作正常。
我仍然不明白为什么控制台打印时带有大括号,也许是一个错误?
我使用新的 Codable 协议将结构转换为 JSON,然后转换为字典以用于测试目的。问题是结构中的字典变量没有被转换回来并保持 Any
而不是 [Int: String]
struct Person: Codable {
var name: String?
var history: [Int: String]
init() {
self.name = "Name"
history = [0: "Test"]
}
}
let person = Person()
let jsonData = try JSONEncoder().encode(person)
let result = try JSONSerialization.jsonObject(with: jsonData, options: [])
let dictionary = result as? [String: Any]
print(dictionary)
这给了我以下结果
Optional(["history": {
0 = Test;
}, "name": Name])
我希望什么时候
Optional(["history":[0: "Test"]], "name": "Test"])
我将不胜感激关于为什么会发生这种情况的任何解释,或者更好的是,如何基本上进行深度 JSON 序列化的解决方案。
我正在添加一个 playground 来演示这个问题: https://www.dropbox.com/s/igpntk7az0hevze/JSONSerialisation.playground.zip
正如您使用JSONEncoder
编码一样,您也可以使用JSONDecoder
解码json数据。在这种情况下,history
是一个不是默认类型之一的字典,因此添加带有自定义的 init(from decoder: Decoder)
将是获得预期字典的一种解决方法。
struct Person: Codable {
var name: String
var history: [Int: String]
init() {
self.name = "Name"
history = [0: "Test"]
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.name = try container.decodeIfPresent(String.self, forKey: .name) ?? "Failed to decode name"
self.history = try container.decodeIfPresent([Int: String].self, forKey: .history) ?? [-1: "Failed to decode history"]
}
}
let person = Person()
do {
let jsonData = try JSONEncoder().encode(person)
if let result = try? JSONDecoder().decode(Person.self, from: jsonData) {
print(result)
}
} catch {
print(error.localizedDescription)
}
原来它是一本字典,只是打印出来就好像它不是字典一样。我认为它不是字典的原因是调用
let history = dictionary["history"] as? [Int: String]
会导致 nil,但原因是 JSON 显然无法处理 [Int: String]
。相反,我的 [Int: String]
已经(可能是通过 JSONSerialization.jsonObject(with: jsonData, options: [])
函数)变成了 [String: Any]
.
let history = dictionary["history"] as? [String: String]
工作正常。
我仍然不明白为什么控制台打印时带有大括号,也许是一个错误?