当您不知道 Swift 中的项目是哪种类型时,如何解码嵌套的 JSON 数据?

How to decode nested JSON data when you don't know which type of the item would be in Swift?

我正在尝试解码来自 API 调用的 JSON 数据,并有一些可解码的 classes 来解码 JSON,但我遇到了一个问题。 在 JSON 中,有一个项目具有相同的名称(假设为“值”),但具有字符串或整数取决于它的“类型”。

有人可以帮我在这种情况下如何构造我的可解码 class 吗? (下面是我的可解码示例 class)

class ExampleClassToDecode: Decodable {
    let type: String
    let value: String? // this item can be either String or Int in the callback JSON data
}

示例JSON

0:{
"type":"type1"
"value":"73%"
}
1:{
"type":"type2"
"value":2
}
2:{
"type":"type3"
"value":NULL
}

您可以使用具有关联值的枚举。

可编码一致性:

struct Example: Codable {
    let type: String
    let value: Value?
}
enum Value: Codable {
    case string(String)
    case int(Int)

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()

        if let string = try? container.decode(String.self) {
            self = .string(string)
            return
        }
        if let int = try? container.decode(Int.self) {
            self = .int(int)
            return
        }

        throw CodableError.failedToDecodeValue
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()

        switch self {
        case .string(let string): try container.encode(string)
        case .int(let int): try container.encode(int)
        }
    }
}
enum CodableError: Error {
    case failedToDecodeValue
}

用法:

let json1 = """
{
    "type": "type1",
    "value": "73%"
}
"""

let json2 = """
{
    "type": "type2",
    "value": 2
}
"""

let json3 = """
{
    "type": "type3",
    "value": null
}
"""
do {
    let data = Data(json1.utf8) // <- Swap this for other JSONs
    let result = try JSONDecoder().decode(Example.self, from: data)
    print(result)

    switch result.value {
    case .string(let string): print("percentage: \(string)")
    case .int(let int): print("counter: \(int)")
    case nil: print("no value")
    }
} catch {
    print(error)
}

我会在您的可解码模型 class 中将其保留为 String,在您的视图控制器中我会使用 type 来了解如何转换 value。 如果是type1那么我就知道这个值是String。 如果是 type2 那么我知道那是一个 Int 所以我将字符串转换为 Int.

编辑:George 示例是一个更好的主意,因为在模型 class 中进行转换,因此您以后无需担心 ViewController。