Swift 4 Decodable:嵌套数组中的结构 [英] Swift 4 Decodable: struct from nested array

查看:133
本文介绍了Swift 4 Decodable:嵌套数组中的结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出以下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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆