Decodable for JSON with two structs under the same tag

Fat*_*tie 0 json ios decodable swift5

I have this json:

{ "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 }}
]}
Run Code Online (Sandbox Code Playgroud)

As you can see for "car" and "house" there are different "object" structs, but both under the tag "object".

It would be ideal if one ended up with something like

struct StuffItem: Decodable {       
  let type: TheType
  let car: Car
  let house: House
}
Run Code Online (Sandbox Code Playgroud)

Is there some Codable, swifty, way to handle this?

vad*_*ian 5

我认为,最快的方法是关联类型的枚举

是有效的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
        }
    }
]}
"""
Run Code Online (Sandbox Code Playgroud)

这些是结构

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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

以及解码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)
}
Run Code Online (Sandbox Code Playgroud)

  • 抱歉耽搁了; 这是一个很好的解释,谢谢。我不知道该怎么做,令人惊讶的是它没有在更多地方得到更清楚的解释!赏金途中 (2认同)