首页 > 解决方案 > 如何解码可变类型的 JSON 数据字段?

问题描述

我从 API 接收 JSON 数据,但有些字段有时是字符串,有时是整数。类似情况的最佳解决方案是什么?

这是我的解码代码:

public struct Nutriments {
    public let energy: String?
    public let energyServing: String?
    public let energy100g: String?

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        energy = try container.decodeIfPresent(String.self, forKey: .energy)
        energy100g = try container.decodeIfPresent(String.self, forKey: .energy100g)
        energyServing = try container.decodeIfPresent(String.self, forKey: .energyServing)
        }
}

JSON 示例:

"nutriments": {
        "energy_100g": 8.97,
        "energy_serving": "55",
        "energy": "7"
}

其他时间是这样的:

"nutriments": {
        "energy_100g": "8.97",
        "energy_serving": 55,
        "energy": 7
}

标签: jsonswiftapidecodable

解决方案


首先责怪服务的所有者发送不一致的数据。

要解码这两种类型,您可以检查init方法中的类型。

至少 API 似乎发送了所有密钥,因此您可以将所有结构成员声明为非可选

public struct Nutriments {

    public let energy: String
    public let energyServing: String
    public let energy100g: String

    public init(from decoder: Decoder) throws {      
        let container = try decoder.container(keyedBy: CodingKeys.self)
        do { energy = try container.decode(String.self, forKey: .energy) }
        } catch DecodingError.typeMismatch { energy = String(try container.decode(Int.self, forKey: .energy)) }
        do { energy100g = try container.decode(String.self, forKey: .energy100g) }
        } catch DecodingError.typeMismatch { energy100g = String(try container.decode(Int.self, forKey: .energy100g)) }
        do { energyServing = try container.decode(String.self, forKey: .energyServing) }
        } catch DecodingError.typeMismatch { energyServing = String(try container.decode(Int.self, forKey: .energyServing)) }
    }
}

推荐阅读