首页 文章

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

提问于
浏览
0

根据要求,我从api得到了两种不同的响应 . 那是

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

另一个回应

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

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

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

2 回答

  • 1

    这是一种方法,它允许您在代码中只有一个属性,而不是两个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)
    }
    
  • -1

    使用像

    struct modelClass : Codable {
    
        let amount : Float?
        let id : Int?
        let price : Float?
        let qty : Int?
        let quantity : Int?
        let shopname : String?
        let storename : String?
    
    
        enum CodingKeys: String, CodingKey {
            case amount = "amount"
            case id = "id"
            case price = "price"
            case qty = "qty"
            case quantity = "quantity"
            case shopname = "shopname"
            case storename = "storename"
        }
        init(from decoder: Decoder) throws {
            let values = try decoder.container(keyedBy: CodingKeys.self)
            amount = try values.decodeIfPresent(Float.self, forKey: .amount)
            id = try values.decodeIfPresent(Int.self, forKey: .id)
            price = try values.decodeIfPresent(Float.self, forKey: .price)
            qty = try values.decodeIfPresent(Int.self, forKey: .qty)
            quantity = try values.decodeIfPresent(Int.self, forKey: .quantity)
            shopname = try values.decodeIfPresent(String.self, forKey: .shopname)
            storename = try values.decodeIfPresent(String.self, forKey: .storename)
        }
    
    
    }
    

相关问题