问题描述
我正在练习我的 Swift 技能,这次我正在尝试制作 Covid-19 跟踪器,为此我发现了这个 API,问题是,{{1} 检索到的格式} 是这样的(更改键以使其更具可读性)
this.segment.value = this.categorias[0];
我制作了以下结构来解码它:
国家
/cases
全部
{
"Country1": {
"All": {
"property1": 0,"property2": "foo"
}
},{
"All": {
"property1": "0","property2": "bar",},"State1": {
"property1": 0,"property3": "foobar"
}
}
}
以米为单位的高程可以采用 String 或 Int 值(长度超过 4 位 > String(附加逗号),否则为 Int)(取自 this answer 的想法
我试着用这种方式解码
struct Country: Codable {
let All: [String: All]
private enum CodingKeys: String,CodingKey {
case All
}
}
我上面的 struct All: Codable {
let confirmed: Int?
let recovered: Int?
let deaths: Int?
let country: String?
let population: Int?
let squareKmArea: Int?
let lifeExpectancy: String?
var elevationInMeters: String?
let continent: String?
let location: String?
let iso: String?
let capitalCity: String?
let lat: String?
let long: String?
let updated: String?
private enum CodingKeys: String,CodingKey {
case confirmed
case recovered
case deaths
case country
case population
case squareKmArea = "sq_km_area"
case lifeExpectancy = "life_expectancy"
case elevationInMeters = "elevation_in_meters"
case continent
case location
case iso
case capitalCity = "capital_city"
case lat
case long
case updated
}
init(confirmed: Int?,recovered: Int?,deaths: Int?,country: String?,population: Int?,squareKmArea: Int?,lifeExpectancy: String?,elevationInMeters: String?,continent: String?,location: String?,iso: String?,capitalCity: String?,lat: String?,long: String?,updated: String?) {
self.confirmed = confirmed
self.recovered = recovered
self.deaths = deaths
self.country = country
self.population = population
self.squareKmArea = squareKmArea
self.lifeExpectancy = lifeExpectancy
self.elevationInMeters = elevationInMeters
self.continent = continent
self.location = location
self.iso = iso
self.capitalCity = capitalCity
self.lat = lat
self.long = long
self.updated = updated
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.confirmed = try container.decodeIfPresent(Int.self,forKey: .confirmed)
self.recovered = try container.decodeIfPresent(Int.self,forKey: .recovered)
self.deaths = try container.decodeIfPresent(Int.self,forKey: .deaths)
self.country = try container.decodeIfPresent(String.self,forKey: .country)
self.population = try container.decodeIfPresent(Int.self,forKey: .population)
self.squareKmArea = try container.decodeIfPresent(Int.self,forKey: .squareKmArea)
self.lifeExpectancy = try container.decodeIfPresent(String.self,forKey: .lifeExpectancy)
self.elevationInMeters = try container.decodeIfPresent(String.self,forKey: .elevationInMeters)
self.continent = try container.decodeIfPresent(String.self,forKey: .continent)
self.location = try container.decodeIfPresent(String.self,forKey: .location)
self.iso = try container.decodeIfPresent(String.self,forKey: .iso)
self.capitalCity = try container.decodeIfPresent(String.self,forKey: .capitalCity)
self.lat = try container.decodeIfPresent(String.self,forKey: .lat)
self.long = try container.decodeIfPresent(String.self,forKey: .long)
self.updated = try container.decodeIfPresent(String.self,forKey: .updated)
do {
self.elevationInMeters = try String(container.decodeIfPresent(Int.self,forKey: .elevationInMeters) ?? 0)
} catch DecodingError.typeMismatch {
print("Not a number")
self.elevationInMeters = try container.decodeIfPresent(String.self,forKey: .elevationInMeters) ?? ""
}
}
}
方法如下所示:
if let decodedData = self.jsonUtilities.decode(json: safeData,as: [String : Country].self) {
print(decodedData)
}
我发现 this answer 他们建议在那里添加所有编码密钥,但这些是一吨。
我没有添加所有的键,因为它是一个 8k+ 行的 JSON,所以我想知道是否有更简单的方法来解码它,因为我想不出更好的方法来用唯一的键解码这个 JSON。
或者,如果我可以忽略所有不是 decode
的键也可能有效,因为我只是想获取每个国家/地区的总数及其位置以将它们放置在地图中。
到目前为止,我收到此错误:
func decode<T: Decodable>(json: Data,as clazz: T.Type) -> T? {
do {
let decoder = JSONDecoder()
let data = try decoder.decode(T.self,from: json)
return data
} catch {
print(error)
print("An error occurred while parsing JSON")
}
return nil
}
afaik 这是因为它没有找到关键的“钻石公主”,它是加拿大的一个州(或者我相信)(根据我的 JSON),因为我没有因为上述原因添加它。
解决方法
当您有动态密钥时,您可以将其解码为 [String: ...]
字典。
JSON 的结构如下:
{
"Canada": {
"All": { ... },"Ontario": { ... },...
},"Mexico": { ... },...
}
所有国家/地区统计数据都有键 "All"
,如果您只需要这些,那么您可以创建以下结构:
struct Country: Decodable {
var all: CountryAll
enum CodingKeys: String,CodingKey {
case all = "All"
}
}
struct CountryAll: Decodable {
var confirmed: Int
var recovered: Int
//.. etc
}
并解码为:
let countries = try JSONDecoder().decode([String: Country].self,from: json)