鉴于JSON:
[{
"name": "TV",
"room": "Living Room"
},
{
"name": "LightBulb 1",
"room": "Living Room"
}
]
struct Room: Decodable {
let name: String
let devices: [Device]
}
struct Device: Decodable {
let name: String
}
如何使用Swift 4 Decodable解码JSON的方式让我的模型结构正确序列化?我想为设备的 room
属性中的每个唯一字符串创建空间,并将这些设备添加到该给定房间的设备列表中 .
一种方法是简单地在没有房间关系的情况下映射它,然后在我获得整个设备列表之后解析该关系,只需运行并按需创建房间,因为我迭代它 . 但这并不像是 The Swift 4™
这样做的方式 . 有更聪明的方法吗?
2 回答
我在这里做出一个假设 - 通过"the Swift 4 Decodable way of decoding JSON"你的意思是调用
try JSONDecoder().decode([Room].self, from: jsonData)
. 如果那个's the case then, to my knowledge, you'运气不好,因为JSONDecoder
将遍历其解析的JSON对象并在每个对象上调用初始化程序Room(from: Decoder)
. 即使您要创建自己的初始化程序,也无法知道其他JSON对象包含的内容 .解决这个问题的一种方法是创建一个反映每个JSON对象属性的中间
Decodable
结构,然后通过遍历这些结构的数组来创建Room
.这是一个例子,可以作为Xcode游乐场使用:
或者 - 也许是更快的Swift4'方式:
注意 - 我在上面的代码中使用了
try?
几次 . 显然你应该正确处理错误 -JSONDecoder
会根据出错的地方给你很好的具体错误! :)从一个对象模型映射到另一个对象模型
和Eivind一起去,因为他已经写了一个很好的答案,我只需加上我的2美分... JSON是一个对象模型,所以我解码JSON对象,然后将这些对象转换为一流的Swift对象 . 只要服务器说JSON,你就必须假设它会在某个时刻发生变化,而你不想要的就是JSON对象模型在Swift世界中流入或指示对象结构甚至是变量名 . 因此,将对象解码为Plain Ol'Swift Objects(POSO)和类型然后进行扩展以处理从这些POSO Decodable到您将构建应用程序的对象的转换是一个非常合理的选择 . 我正在工作的操场位于下方,但是Eivind打败了我,并在他的第二个例子中遇到了生成最终的纯Swift对象的麻烦 .
Apple关于JSON处理的博客有这个不错的报价
Working with JSON in Swift