Decodable for JSON with two structs under the same tag

前端 未结 3 1465
灰色年华
灰色年华 2021-01-27 08:44

I have this json:

{ \"stuff\": [
 {
 \"type\":\"car\",
 \"object\":{
  \"a\":66,
  \"b\":66,
  \"c\":66 }},
 {
 \"type\":\"house\",
 \"object\":{
  \"d\":66,
  \         


        
3条回答
  •  南笙
    南笙 (楼主)
    2021-01-27 09:27

    The swiftiest way in my opinion is an enum with associated types

    This is valid JSON

    let jsonString = """
    { "stuff": [
        {
        "type":"car",
        "object":{
            "a":66,
            "b":66,
            "c":66
            }
        },{
        "type":"house",
        "object":{
            "d":66,
            "e":66,
            "f":66
            }
        },{
        "type":"car",
        "object":{
            "a":66,
            "b":66,
            "c":66
            }
        }
    ]}
    """
    

    These are the structs

    struct Root : Decodable {
        let stuff : [Object]
    }
    
    enum Type : String, Decodable { case car, house }
    
    struct Car : Decodable {
        let a, b, c : Int
    }
    
    struct House : Decodable {
        let d, e, f : Int
    }
    
    
    enum Object : Decodable {
        case house(House), car(Car)
    
        private enum CodingKeys : String, CodingKey { case type, object }
    
        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            let type = try container.decode(Type.self, forKey: .type)
            switch type {
            case .car:
                let carData = try container.decode(Car.self, forKey: .object)
                self = .car(carData)
            case .house:
                let houseData = try container.decode(House.self, forKey: .object)
                self = .house(houseData)
            }
        }
    }
    

    And the code to decode the JSON

    do {
        let result = try JSONDecoder().decode(Root.self, from: Data(jsonString.utf8))
        let objects = result.stuff
        for object in objects {
            switch object {
            case .car(let car): print(car)
            case .house(let house): print(house)
            }
        }
    } catch {
        print(error)
    }
    

提交回复
热议问题