一尘不染

Swift Codable多种类型

swift

我尝试解析返回json对象的api。我的问题是,在以下示例中,某些键有时是字符串,有时是类似“ Value”键的对象:

[
{
    "Description": null,
    "Group": "Beskrivning av enheten",
    "GroupDescription": null,
    "Id": "Description",
    "Name": "Mer om enheten",
    "Value": "Det finns möjlighet till parkering på gatorna runt om, men det är kantstenar och ganska branta backar för att komma upp till lekplatsen.\r\n\r\nUtanför själva lekplatsen finns en gungställning med en plan omväg in. Alla lekredskap står i sandytor, det finns många kanter. Runt hela lekplatsen går ett staket med öppningar i olika riktningar."
},
{
    "Description": null,
    "Group": "Bilder och film",
    "GroupDescription": null,
    "Id": "Image",
    "Name": "Huvudbild",
    "Value": {
        "__type": "FileInfo",
        "Id": "8871b3b1-14f4-4054-8728-636d9da21ace",
        "Name": "ullerudsbacken.jpg"
    }
}
]

我的结构看起来像这样:

struct ServiceUnit: Codable {
        let description: String?
        let group: String?
        let groupDescription: String?
        let id: String
        let name: String
        var value: String?
        struct ServiceUnitTypeInfo: Codable {
            let id: String
            let singularName: String?
            enum CodingKeys: String, CodingKey {
                case id = "Id"
                case singularName = "SingularName"
            }
        }
        let serviceUnitTypeInfo: ServiceUnitTypeInfo?
        let values: [String]?
        enum CodingKeys: String, CodingKey {
            case description = "Description"
            case group = "Group"
            case groupDescription = "GroupDescription"
            case id = "Id"
            case name = "Name"
            case value = "Value"
            case serviceUnitTypeInfo = "ServiceUnitTypeInfo"
            case values = "Values"
            case image = "Image"
        }
    }

我必须告诉我我完全迷路了(是的,我是个迅速的初学者),我找不到解决我问题的方法。我知道我必须使用自定义init,但我不知道如何。


阅读 557

收藏
2020-07-07

共1个答案

一尘不染

你可以试试

struct Root: Codable {
    let description,id: String
    let group,groupDescription: String?
    let name: String
    let value: MyValue

    enum CodingKeys: String, CodingKey {
        case description = "Description"
        case group = "Group"
        case groupDescription = "GroupDescription"
        case id = "Id"
        case name = "Name"
        case value = "Value"
    }
}

enum MyValue: Codable {
    case string(String)
    case innerItem(InnerItem)

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let x = try? container.decode(String.self) {
            self = .string(x)
            return
        }
        if let x = try? container.decode(InnerItem.self) {
            self = .innerItem(x)
            return
        }
        throw DecodingError.typeMismatch(MyValue.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for MyValue"))
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .string(let x):
            try container.encode(x)
        case .innerItem(let x):
            try container.encode(x)
        }
    }
}

struct InnerItem: Codable {
    let type, id, name: String

    enum CodingKeys: String, CodingKey {
        case type = "__type"
        case id = "Id"
        case name = "Name"
    }
}

do {
  let result = try JSONDecoder().decode([Root].self,from:data)
  print(result)
}
catch {
  print(error)
}
2020-07-07