使用 Swift 中的变量解码 JSON

Decode JSON with variables in Swift

我正在尝试解码 JSON-Swift

中的此类数据
{"Total ingredients":[{"PE-LLD":"54.4 %"},{"PE-HD":"41.1 %"},{"TiO2":"4.5 %"}]}

成分的名称和数量是可变的。因此我只能用这种结构解码它:

struct Product: Codable {
    var total_ingredients: [[String: String]]?

    private enum CodingKeys : String, CodingKey {   
        case total_ingredients = "Total ingredients"
    }
}

但我希望能够在任一字典中解码它:var total_ingredients: [String: String]? 或我在对象数组中的首选:var total_ingredients: [Ingredient]?

struct Ingredient: Codable {
    var name: String
    var percentage: String
}

我已经尝试使用扩展来解决我的问题,但它不起作用,我认为这不是正确的方法:

extension Ingredient {
    init(_ ingredient: [String: String]) {
        var key: String = ""
        var value: String = ""
        
        for data in ingredient {
            key = data.key
            value = data.value
        }
        
        self = .init(name: key, percentage: value)
    }
}

提前致谢:)

您必须实施 init(from decoder 并将字典数组映射到 Ingredient 个实例

struct Product: Decodable {
    let totalIngredients: [Ingredient]

    private enum CodingKeys : String, CodingKey { case totalIngredients = "Total ingredients" }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let ingredientData = try container.decode([[String:String]].self, forKey: .totalIngredients)
        totalIngredients = ingredientData.compactMap({ dict -> Ingredient? in
           guard let key = dict.keys.first, let value = dict[key] else { return nil }
           return Ingredient(name: key, percentage: value)
        })
    }
}

struct Ingredient {
    let name, percentage: String
}

let jsonString = """
{"Total ingredients":[{"PE-LLD":"54.4 %"},{"PE-HD":"41.1 %"},{"TiO2":"4.5 %"}]}
"""

let data = Data(jsonString.utf8)

do {
    let result = try JSONDecoder().decode(Product.self, from: data)
    print(result)
} catch {
    print(error)
}

不需要扩展。