Swift 4 Decodable:嵌套数组中的结构 [英] Swift 4 Decodable: struct from nested array
问题描述
给出以下JSON文档,我想创建一个具有四个属性的struct
:filmCount
(Int),year
(Int),category
(String)和actor
(Actor数组) ).
Given the following JSON document I'd like to create a struct
with four properties: filmCount
(Int), year
(Int), category
(String), and actor
(Actor array).
{
"filmCount": 5,
"year": 2018,
"category": "Other",
"actors":{
"nodes":[
{
"actor":{
"id":0,
"name":"Daniel Craig"
}
},
{
"actor":{
"id":1,
"name":"Naomie Harris"
}
},
{
"actor":{
"id":2,
"name":"Rowan Atkinson"
}
}
]
}
}
PlacerholderData
是一个结构,用于存储三个主要属性以及应该从JSON对象的actors
属性内的嵌套nodes
容器中检索的actor列表.
PlacerholderData
is a struct storing the three main properties and the list of actors which should be retrieved from the nested nodes
container within the actors
property from the JSON object.
PlacerholderData:
PlacerholderData:
struct PlaceholderData: Codable {
let filmCount: Int
let year: Int
let category: String
let actors: [Actor]
}
Actor.swift:
Actor.swift:
struct Actor: Codable {
let id: Int
let name: String
}
我正在尝试通过提供自己的init
来手动初始化解码器容器中的值,以实现此目的.我该如何解决此问题,而不必具有存储nodes
对象的中间结构?
I am attempting to do this through providing my own init
to initialise the values from the decoder's container manually. How can I go about fixing this without having to have an intermediate struct storing a nodes
object?
推荐答案
您可以使用 nestedContainer(keyedBy:)和 nestedUnkeyedContainer(forKey:)来解码嵌套数组并像这样的字典将其变成您想要的结构.您在 init(decoder:)中的解码可能看起来像这样,
You can use nestedContainer(keyedBy:) and nestedUnkeyedContainer(forKey:) for decoding nested array and dictionary like this to turn it into your desired structure. Your decoding in init(decoder: ) might look something like this,
用于解码的演员扩展,
extension Actor: Decodable {
enum CodingKeys: CodingKey { case id, name }
enum ActorKey: CodingKey { case actor }
init(from decoder: Decoder) throws {
let rootKeys = try decoder.container(keyedBy: ActorKey.self)
let actorContainer = try rootKeys.nestedContainer(keyedBy: CodingKeys.self,
forKey: .actor)
try id = actorContainer.decode(Int.self,
forKey: .id)
try name = actorContainer.decode(String.self,
forKey: .name)
}
}
用于解码的PlaceholderData扩展
PlaceholderData extension for decoding,
extension PlaceholderData: Decodable {
enum CodingKeys: CodingKey { case filmCount, year, category, actors }
enum NodeKeys: CodingKey { case nodes }
init(from decoder: Decoder) throws {
let rootContainer = try decoder.container(keyedBy: CodingKeys.self)
try filmCount = rootContainer.decode(Int.self,
forKey: .filmCount)
try year = rootContainer.decode(Int.self,
forKey: .year)
try category = rootContainer.decode(String.self,
forKey: .category)
let actorsNode = try rootContainer.nestedContainer(keyedBy: NodeKeys.self,
forKey: .actors)
var nodes = try actorsNode.nestedUnkeyedContainer(forKey: .nodes)
var allActors: [Actor] = []
while !nodes.isAtEnd {
let actor = try nodes.decode(Actor.self)
allActors += [actor]
}
actors = allActors
}
}
然后,您可以像这样解码它,
Then, you can decode it like this,
let decoder = JSONDecoder()
do {
let placeholder = try decoder.decode(PlaceholderData.self, from: jsonData)
print(placeholder)
} catch {
print(error)
}
这里,基本思想是使用 nestedContainer(keyedBy:)解码字典容器,并使用 nestedUnkeyedContainer(forKey:)
Here, the basic idea is to decode dictionary container using nestedContainer(keyedBy:) and array container using nestedUnkeyedContainer(forKey:)
这篇关于Swift 4 Decodable:嵌套数组中的结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!