问题描述
我正在尝试在 Swift 中解码这种类型的 JSON 数据
{"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)
}
不需要扩展。