Swift 4 Decodable: struct from nested array

后端 未结 1 1588
被撕碎了的回忆
被撕碎了的回忆 2021-02-15 14:05

Given the following JSON document I\'d like to create a struct with four properties: filmCount (Int), year (Int), category (S

1条回答
  •  感动是毒
    2021-02-15 14:51

    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,

    Actor extension for decoding,

    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 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)
    }
    

    Here, the basic idea is to decode dictionary container using nestedContainer(keyedBy:) and array container using nestedUnkeyedContainer(forKey:)

    0 讨论(0)
提交回复
热议问题