这是我的json,我想用JSONDecoder解码,但很困难,因为它不能解码。
{
"Afghanistan": [
{
"city": "Kabul",
"lat": "34.5167",
"lng": "69.1833",
"state": "Kābul",
"country": "Afghanistan"
},
{
"city": "Karukh",
"lat": "34.4868",
"lng": "62.5918",
"state": "Herāt",
"country": "Afghanistan"
},
{
"city": "Zarghūn Shahr",
"lat": "32.85",
"lng": "68.4167",
"state": "Paktīkā",
"country": "Afghanistan"
}
],
"Albania": [
{
"city": "Tirana",
"lat": "41.3275",
"lng": "19.8189",
"state": "Tiranë",
"country": "Albania"
},
{
"city": "Pukë",
"lat": "42.0333",
"lng": "19.8833",
"state": "Shkodër",
"country": "Albania"
}
]}
你有什么建议来解码它?
我正在尝试以下方法
let locationData: Countries = load("Countries.json")
func load<T: Decodable>(_ filename: String) -> T {
let data: Data
guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
else {
fatalError("Couldn't find \(filename) in main bundle.")
}
do {
data = try Data(contentsOf: file)
} catch {
fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
}
}
struct Country: Codable, Identifiable {
var id = UUID()
let city, lat, lng: String
let state: String?
let country: String
}
typealias Countries = [String: [Country]]
但得到的错误是
无法解析国家.json为Dictionary>: keyNotFound(CodingKeys(stringValue: "id", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Albania", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "没有与CodingKeys(stringValue: \"id/", intValue: nil)(\"id/")键相关联的值。", underlyingError: nil))。
因为这个属性 id
并不是json的一部分,你需要通过添加一个CodingKey枚举到 Country
enum CodingKeys: String, CodingKey {
case city, lat, lng, state, country
}
CodingKey枚举也让你有机会为你的struct属性使用更好的名字,如果你想的话,并在枚举中把它们映射到json键。
struct Country: Codable, Identifiable {
var id = UUID()
let city: String
let latitude: String
let longitude: String
let state: String?
let country: String
enum CodingKeys: String, CodingKey {
case city
case latitude = "lat"
case longitude = "lng"
case state, country
}
}
这是错误的相关部分。keyNotFound(CodingKeys(stringValue: "id", intValue: nil)
. 它告诉你,它在每个JSON对象中寻找一个 "id "键,但没有找到。
它之所以要找一个id,是因为默认实现的 Codable
结构的协议会尝试反序列化所有你定义的属性。你定义了一个 var id
属性,所以它正在寻找这个属性。
由于你不想反序列化id属性,你需要自定义你的结构,使它不使用默认的实现。如何做到这一点的文档在这里。自定义类型的编码和解码
在您的情况下,您只需要定义一个 CodingKeys
枚举在你的结构中,这样它就知道要寻找哪些键。
enum CodingKeys: String, CodingKey {
case city, lat, lng, state, country
}