Ios 使用带有(无)键的字典解码JSON
我很难用structs解码一个简单的JSON api结果 这是JSON结构(它的一部分): 这是我创建的结构:Ios 使用带有(无)键的字典解码JSON,ios,swiftui,Ios,Swiftui,我很难用structs解码一个简单的JSON api结果 这是JSON结构(它的一部分): 这是我创建的结构: struct Countries: Codable { var countries: [Country] } struct Country: Codable, Identifiable { var id = UUID() var code: String var name: String } 我使用API来尝试解码它: let decodedResp
struct Countries: Codable {
var countries: [Country]
}
struct Country: Codable, Identifiable {
var id = UUID()
var code: String
var name: String
}
我使用API来尝试解码它:
let decodedResponse = try JSONDecoder().decode(Countries.self, from: data)
目前,这是一个错误:
No value associated with key CodingKeys(stringValue: "countries", intValue: nil) ("countries").
正如我正确理解的那样,JSON结果有两个方面,键和值。本例中的键是国家代码(两个字母),值是国家名称。我确实想在我的应用程序中同时使用这两种方法,但我很难使用struct同时使用键和值。目前的错误也是因为字典本身没有键。但我也可以想象单个国家的值也不会起作用。实现自定义
编码器和解码器逻辑可以帮助在预期的json[String:String]
和国家之间转换
struct Countries: Codable {
struct Country {
let code: String
let name: String
}
let countries: [Country]
//custom decoder logic; from json to model
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let dict = try container.decode([String:String].self)
countries = dict.map(Country.init)
}
//custom encoder logic; from model to json
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
var dict = [String:String]()
countries.forEach { (country) in
dict[country.code] = country.name
}
try container.encode(dict)
}
}
用法示例**:
**忽略强制展开,这只是测试代码我会将其解码为[String:String]
,然后通过在字典上循环手动将数据转换为所需的数据结构。@luk2302我这样尝试过:let decodedResponse=try JSONDecoder().decode([String:String].self,from:data)DispatchQueue.main.async(){for item in decodedResponse{countries.append(Country(code:item.key,name:item.value))}
和print(countries)结果为:countries.Country(code:“ar”,name:“阿根廷”)、countries.Country(code:“gu”,name:“关岛”)等
但在我的列表中没有显示任何国家:ForEach(countries,id:\.self){country in Text(country.name)}
谢谢!我确实管理了它,让它工作起来。我使用forEach将每个国家项添加到数组中,如下所示:result.countries.forEach{countries.append($0)}
并且只使用可解码项,因为我不需要将其编码回json。
struct Countries: Codable {
struct Country {
let code: String
let name: String
}
let countries: [Country]
//custom decoder logic; from json to model
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let dict = try container.decode([String:String].self)
countries = dict.map(Country.init)
}
//custom encoder logic; from model to json
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
var dict = [String:String]()
countries.forEach { (country) in
dict[country.code] = country.name
}
try container.encode(dict)
}
}
let jsonData = """
{
"ad": "Andorra",
"ae": "United Arab Emirates",
"af": "Afghanistan",
"ag": "Antigua and Barbuda",
"ai": "Anguilla",
"al": "Albania"
}
""".data(using: .utf8)!
do {
let result = try JSONDecoder().decode(Countries.self, from: jsonData)
result.countries.forEach { print($0) }
let data = try JSONEncoder().encode(result)
let json = String(data: data, encoding: .utf8)!
print(json)
} catch {
print(error)
}