Ios 使用带有(无)键的字典解码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

我很难用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 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)
}