json - 使用 Codable 在一个模型类中解码两个不同的 JSON 响应

标签 json swift decodable

根据需求,我从 api 得到了两种不同的响应。也就是

{
  "shopname":"xxx",
  "quantity":4,
  "id":1,
  "price":200.00,
}

另一个回应

{
  "storename":"xxx",
  "qty":4,
  "id":1,
  "amount":200.00,
}

这里两个 json 值都在同一个模型类中解码。请帮助我解决这个问题。

是否可以在单个变量中设置值,例如 qtyquantity 两者都存储在基于关键参数可用性的相同变量中

最佳答案

这里有一种方法可以让你的代码中只有一个属性,而不是两个 Optionals:

定义一个结构,其中包含您需要的所有属性,以及您希望在代码中使用的名称。然后,定义两个 CodingKey 枚举,将这些属性映射到两种不同的 JSON 格式并实现自定义初始化程序:

let json1 = """
{
    "shopname":"xxx",
    "quantity":4,
    "id":1,
    "price":200.00,
}
""".data(using: .utf8)!

let json2 = """
{
    "storename":"xxx",
    "qty":4,
    "id":1,
    "amount":200.00,
}
""".data(using: .utf8)!

struct DecodingError: Error {}

struct Model: Decodable {
    let storename: String
    let quantity: Int
    let id: Int
    let price: Double

    enum CodingKeys1: String, CodingKey {
        case storename = "shopname"
        case quantity
        case id
        case price
    }

    enum CodingKeys2: String, CodingKey {
        case storename
        case quantity = "qty"
        case id
        case price = "amount"
    }

    init(from decoder: Decoder) throws {
        let container1 = try decoder.container(keyedBy: CodingKeys1.self)
        let container2 = try decoder.container(keyedBy: CodingKeys2.self)

        if let storename = try container1.decodeIfPresent(String.self, forKey: CodingKeys1.storename) {
            self.storename = storename
            self.quantity = try container1.decode(Int.self, forKey: CodingKeys1.quantity)
            self.id = try container1.decode(Int.self, forKey: CodingKeys1.id)
            self.price = try container1.decode(Double.self, forKey: CodingKeys1.price)
        } else if let storename = try container2.decodeIfPresent(String.self, forKey: CodingKeys2.storename) {
            self.storename = storename
            self.quantity = try container2.decode(Int.self, forKey: CodingKeys2.quantity)
            self.id = try container2.decode(Int.self, forKey: CodingKeys2.id)
            self.price = try container2.decode(Double.self, forKey: CodingKeys2.price)
        } else {
            throw DecodingError()
        }
    }
}


do {
    let j1 = try JSONDecoder().decode(Model.self, from: json1)
    print(j1)
    let j2 = try JSONDecoder().decode(Model.self, from: json2)
    print(j2)
} catch {
    print(error)
}

关于json - 使用 Codable 在一个模型类中解码两个不同的 JSON 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53313725/

相关文章:

ios - 转换时变量为空

ios - Swift:阻止滚动内的图像上下移动

swift - 如何从iOS SQLite数据库保存和获取数据?

html - 解码包含 HTML 的 json

swift - 如何扩展 Decodable 以从字典初始化?

json - 在 Golang 中访问 map[string]interface{} 类型的嵌套映射

html - 将 Instagram API 用于简单网页

java - Jackson - 反序列化 JSON 字符串 - TypeReference 与 TypeFactory.constructCollectionType

javascript - 在Javascript中更新JSON数据的引用问题

Swift 开关和 case 函数处理