json - 使用值有时是 Int 有时是 String 的 codable

标签 json swift swift4 codable

我有一个 API 有时会以 Int 形式返回 JSON 中的特定键值(在本例中为 id),有时会返回相同的键值作为 String。我如何使用 codable 来解析该 JSON?

struct GeneralProduct: Codable {
    var price: Double!
    var id: String?
    var name: String!

    private enum CodingKeys: String, CodingKey {
        case price = "p"
        case id = "i"
        case name = "n"
    }

    init(price: Double? = nil, id: String? = nil, name: String? = nil) {
        self.price = price
        self.id = id
        self.name = name
    }
}

我不断收到此错误消息:应解码字符串但发现了一个数字。它返回一个数字的原因是因为 id 字段为空,当 id 字段为空时,它默认返回 0 作为 ID,codable 将其标识为数字。我基本上可以忽略 ID key ,但据我所知,codable 没有给我忽略它的选项。处理此问题的最佳方法是什么?

这是 JSON。 super 简单

工作

{
  "p":2.12,
  "i":"3k3mkfnk3",
  "n":"Blue Shirt"
}

错误 - 因为系统中没有 id,它返回 0 作为默认值,codable 显然将其视为与字符串相对的数字。

{
  "p":2.19,
  "i":0,
  "n":"Black Shirt"
}

最佳答案

struct GeneralProduct: Codable {
    var price: Double?
    var id: String?
    var name: String?
    private enum CodingKeys: String, CodingKey {
        case price = "p", id = "i", name = "n"
    }
    init(price: Double? = nil, id: String? = nil, name: String? = nil) {
        self.price = price
        self.id = id
        self.name = name
    }
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        price = try container.decode(Double.self, forKey: .price)
        name = try container.decode(String.self, forKey: .name)
        do {
            id = try String(container.decode(Int.self, forKey: .id))
        } catch DecodingError.typeMismatch {
            id = try container.decode(String.self, forKey: .id)
        }
    }
}

let json1 = """
{
"p":2.12,
"i":"3k3mkfnk3",
"n":"Blue Shirt"
}
"""

let json2 = """
{
"p":2.12,
"i":0,
"n":"Blue Shirt"
}
"""

do {
    let product = try JSONDecoder().decode(GeneralProduct.self, from: Data(json2.utf8))
    print(product.price ?? "nil")
    print(product.id ?? "nil")
    print(product.name ?? "nil")
} catch {
    print(error)
}

编辑/更新:

当您的 api 返回 0 时,您也可以简单地将 nil 分配给您的 id:

do {
    let value = try container.decode(Int.self, forKey: .id)
    id = value == 0 ? nil : String(value)
} catch DecodingError.typeMismatch {
    id = try container.decode(String.self, forKey: .id)
}

关于json - 使用值有时是 Int 有时是 String 的 codable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55519548/

相关文章:

ios - 将数据从 View Controller 传递到 tabbarviewcontroller

ios - 单击图像时如何在屏幕上随机移动 UIimageView

ios - 'filter' 与嵌套过滤器的使用不明确

Swift:- 在自定义 tableview 单元格中单击按钮时将标签值增加 1

jquery getJSON函数计时问题

json - Swift 4 可解码 : struct from nested array

c# - 使用 C# 反序列化 JSON

swift - 如何从点击中获取 SKSpriteNode 子类对象

javascript - Highcharts 系列数据数组

c# - 获取json数据和图片