解码嵌套的 json swift
Decode nested jsons swift
大家好,我有一个与 Swift 中的 Encodable 协议相关的小问题。
我有以下 json 文件:
let magicJson = """
{
"value": [
{
"scheduleId": "magic@yahoo.com",
"somethingEventMoreMagical": "000220000"
}
]
}
""".data(using: .utf8)!
为了解码,我试图避免必须创建两个都与 Decodable 一起使用的对象,并且第一个对象具有第二个对象的数组。我想将该对象展平成这样的东西:
struct MagicalStruct: Decodable {
private enum CodingKeys: String, CodingKey {
case value
}
private enum ScheduleCodingKeys: String, CodingKey {
case roomEmail = "scheduleId"
}
let roomEmail: String
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let magicContainer = try container.nestedContainer(keyedBy: ScheduleCodingKeys.self, forKey: .value)
roomEmail = try magicContainer.decode(String.self, forKey: ScheduleCodingKeys.roomEmail)
}
}
然而,当我尝试以下代码时:JSONDecoder().decode(MagicalStruct.self, magicJson)
我得到它需要一个数组但得到一个字典。另一方面,当我使用 JSONDecoder().decode([MagicalStruct].self, magicJson)
时,我得到它接收一个数组但需要一个字典。
有谁知道为什么会这样?
首先,当您解码结构时使用:
JSONDecoder().decode(MagicalStruct.self, magicJson)
您正在尝试提取 单个 对象:let roomEmail: String
.
但是,您的输入 JSON 包含一组包含电子邮件的对象。这意味着您的代码:
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let magicContainer = try container.nestedContainer(keyedBy: ScheduleCodingKeys.self, forKey: .value)
roomEmail = try magicContainer.decode(String.self, forKey: ScheduleCodingKeys.roomEmail)
}
尝试解码单个电子邮件,但有一个集合(在您的示例中带有 one 元素 - 这就是它可能令人困惑的原因)。
还有你的错误Expected to decode Dictionary<String, Any> but found an array instead
在线:
let magicContainer = try container.nestedContainer(keyedBy: ScheduleCodingKeys.self, forKey: .value)
你需要解码一个数组:
var magicContainer = try container.nestedUnkeyedContainer(forKey: .value)
但是你有一个包含 scheduleId
和 somethingEventMoreMagical
键的对象数组。您想如何将所有值分配给您的一个 let roomEmail: String
变量?
您可以改为解码字典:
let result = try JSONDecoder().decode([String: [MagicalStruct]].self, from: magicJson)
print(result["value"]!) // prints [MagicalStruct(roomEmail: "magic@yahoo.com")]
你可以简化你的 MagicalStruct
:
struct MagicalStruct: Decodable {
enum CodingKeys: String, CodingKey {
case roomEmail = "scheduleId"
}
let roomEmail: String
}
大家好,我有一个与 Swift 中的 Encodable 协议相关的小问题。
我有以下 json 文件:
let magicJson = """
{
"value": [
{
"scheduleId": "magic@yahoo.com",
"somethingEventMoreMagical": "000220000"
}
]
}
""".data(using: .utf8)!
为了解码,我试图避免必须创建两个都与 Decodable 一起使用的对象,并且第一个对象具有第二个对象的数组。我想将该对象展平成这样的东西:
struct MagicalStruct: Decodable {
private enum CodingKeys: String, CodingKey {
case value
}
private enum ScheduleCodingKeys: String, CodingKey {
case roomEmail = "scheduleId"
}
let roomEmail: String
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let magicContainer = try container.nestedContainer(keyedBy: ScheduleCodingKeys.self, forKey: .value)
roomEmail = try magicContainer.decode(String.self, forKey: ScheduleCodingKeys.roomEmail)
}
}
然而,当我尝试以下代码时:JSONDecoder().decode(MagicalStruct.self, magicJson)
我得到它需要一个数组但得到一个字典。另一方面,当我使用 JSONDecoder().decode([MagicalStruct].self, magicJson)
时,我得到它接收一个数组但需要一个字典。
有谁知道为什么会这样?
首先,当您解码结构时使用:
JSONDecoder().decode(MagicalStruct.self, magicJson)
您正在尝试提取 单个 对象:let roomEmail: String
.
但是,您的输入 JSON 包含一组包含电子邮件的对象。这意味着您的代码:
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let magicContainer = try container.nestedContainer(keyedBy: ScheduleCodingKeys.self, forKey: .value)
roomEmail = try magicContainer.decode(String.self, forKey: ScheduleCodingKeys.roomEmail)
}
尝试解码单个电子邮件,但有一个集合(在您的示例中带有 one 元素 - 这就是它可能令人困惑的原因)。
还有你的错误Expected to decode Dictionary<String, Any> but found an array instead
在线:
let magicContainer = try container.nestedContainer(keyedBy: ScheduleCodingKeys.self, forKey: .value)
你需要解码一个数组:
var magicContainer = try container.nestedUnkeyedContainer(forKey: .value)
但是你有一个包含 scheduleId
和 somethingEventMoreMagical
键的对象数组。您想如何将所有值分配给您的一个 let roomEmail: String
变量?
您可以改为解码字典:
let result = try JSONDecoder().decode([String: [MagicalStruct]].self, from: magicJson)
print(result["value"]!) // prints [MagicalStruct(roomEmail: "magic@yahoo.com")]
你可以简化你的 MagicalStruct
:
struct MagicalStruct: Decodable {
enum CodingKeys: String, CodingKey {
case roomEmail = "scheduleId"
}
let roomEmail: String
}