如何使用未知密钥解码json [英] How to decode json with unknown key

查看:90
本文介绍了如何使用未知密钥解码json的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每个人,如果字段之一未知,如何序列化json结构?

everyone, how to serialize json struct, if one of field unknown?

我的json是:

 {"brands":{"any":false,"19":{"is_all":false,"values":[185,182,178],"include":true},"23":{"is_all":false,"values":[198,199,201],"include":true}},"price":[2000,10000],"year":[1990,2018],"fuel_type":[1,2],"engine_capacity":[\"1.8\",\"4.8\"],"color":[1,2,3],"gearbox_id":[2],"is_georgia":false}

但是:

"19":{"is_all":false,"values":[185,182,178],"include":true}

"19":{"is_all":false,"values":[185,182,178],"include":true}

"23":{"is_all":false,"values":[198,199,201],"include":true}

"23":{"is_all":false,"values":[198,199,201],"include":true}

19和23-是字符串未知值,由API生成.

19 and 23 - is string unknown value, it's generated by API.

所以我的结构是:

    struct auto_order_model: Decodable {
        var brands: brand_details             <---- this is problem
        let price: [Int]
        let year: [Int]
        let fuel_type: [Int]
        let engine_capacity: [String]
        let color: [Int]
        let gearbox_id: [Int]
        let is_georgia: Bool
    }
    struct brand_details: Decodable {
        var any: Bool
        var brand_num: [models]?
    }
    struct models: Decodable {
        var is_all: Bool
        var values: [Int]
        var include: Bool
    }

我这样解码json:

    do {
        let data = try JSONDecoder().decode(auto_order_model.self, from: json)
        print(data)
    }catch {
        print("JSON Error")
    }

因此,在输出中,我得到brand_num的 nil :

so, on output I get nil of brand_num:

▿ auto_order_model #1
  ▿ brands : brand_details #1
    - any : false
    - brand_num : nil
  ▿ price : 2 elements
    - 0 : 2000
    - 1 : 10000
  ▿ year : 2 elements
    - 0 : 1990
    - 1 : 2018
  ▿ fuel_type : 2 elements
    - 0 : 1
    - 1 : 2
  ▿ engine_capacity : 2 elements
    - 0 : "1.8"
    - 1 : "4.8"
  ▿ color : 3 elements
    - 0 : 1
    - 1 : 2
    - 2 : 3
  ▿ gearbox_id : 1 element
    - 0 : 2
  - is_georgia : false

推荐答案

这是通过为品牌号动态创建必要的编码键来完成的,如下所示:

This is done by creating the necessary coding keys for the brand number dynamically, like this:

struct AutoOrderModel: Decodable {
    var brands: BrandList
    let price: [Int]
    let year: [Int]
    let fuelType: [Int]
    let engineCapacity: [String]
    let color: [Int]
    let gearboxId: [Int]
    let isGeorgia: Bool

    enum CodingKeys: String, CodingKey {
        case brands, price, year, color
        case fuelType = "fuel_type"
        case engineCapacity = "engine_capacity"
        case gearboxId = "gearbox_id"
        case isGeorgia = "is_georgia"
    }
}

struct BrandList: Decodable {
    var any: Bool = false
    let brands: [String: Models]

    struct DetailKey: CodingKey {
        var stringValue: String
        var intValue: Int?
        init?(stringValue: String) { 
           self.stringValue = stringValue 
        }
        init?(intValue: Int) { 
            self.stringValue = "\(intValue)"; 
            self.intValue = intValue 
        }
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: DetailKey.self)

        var brands = [String: Models]()
        for key in container.allKeys {
            if let model = try? container.decode(Models.self, forKey: key) {
                brands[key.stringValue] = model
            } else if let any = try? container.decode(Bool.self, forKey: key) {
                self.any = any
            }
        }

        self.brands = brands
    }
}

struct Models: Decodable {
    var isAll: Bool
    var values: [Int]
    var include: Bool

    enum CodingKeys: String, CodingKey {
        case isAll = "is_all"
        case values, include
    }
}

这篇关于如何使用未知密钥解码json的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆