json - 反序列化 JSON swift 4.2
问题描述
我尝试使用 Decodable 协议反序列化我的 JSON,我也将 enum 与 CodingKey 一起使用,但它不起作用。我只需要嵌套数组(以“indicator”开头),并且只需要几个字段(它们都在结构中)。我尝试了很多不同的选项,但不幸的是.. PS 我也尝试在没有 CodingKey 的情况下做到这一点。无论如何响应是:“Swift.DecodingError.keyNotFound(CodingKeys(stringValue:“country”,intValue:nil)”我读到这个,也许数组是一个原因(我的意思是这个奇怪的intValue)?
JSON
[
{
"page":1,
"pages":2,
"per_page":50,
"total":59,
"sourceid":"2",
"lastupdated":"2019-03-21"
},
[
{
"indicator":{
"id":"IP.PAT.RESD",
"value":"Patent applications, residents"
},
"country":{
"id":"SS",
"value":"South Sudan"
},
"countryiso3code":"SSD",
"date":"2018",
"value":null,
"unit":"",
"obs_status":"",
"decimal":0
},
{
"indicator":{
"id":"IP.PAT.RESD",
"value":"Patent applications, residents"
},
"country":{
"id":"SS",
"value":"South Sudan"
},
"countryiso3code":"SSD",
"date":"2017",
"value":null,
"unit":"",
"obs_status":"",
"decimal":0
},
...
]
]
我的代码
struct CountryObject: Decodable{
var country: CountryInfo
var date: Int
var value: Int?
private enum RawValues: String, Decodable{
case date = "date"
case vallue = "value"
}
}
struct CountryInfo: Decodable{//Country names
var id: String?
var value: String?
private enum RawValues: String, Decodable{
case id = "id"
case value = "value"
}
}//
let urlString = "https://api.worldbank.org/v2/country/SS/indicator/IP.PAT.RESD?format=json"
guard let url = URL(string: urlString) else {return}
URLSession.shared.dataTask(with: url) {(data,response,error) in
guard let data = data else {return}
guard error == nil else {return}
do{
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let countryObject = try! decoder.decode([CountryObject].self, from: data)
print(countryObject)
}catch let error{
print(error)
}
}.resume()
解决方案
创建一个根结构并使用解码数组unkeyedContainer
struct Root : Decodable {
let info : Info
let countryObjects : [CountryObject]
init(from decoder: Decoder) throws {
var arrayContrainer = try decoder.unkeyedContainer()
info = try arrayContrainer.decode(Info.self)
countryObject = try arrayContrainer.decode([CountryObject].self)
}
}
struct Info : Decodable {
let page, pages, perPage: Int
let lastupdated: String
}
struct CountryObject : Decodable {
let country: CountryInfo
let date: String
let value: Int?
}
struct CountryInfo : Decodable { //Country names
let id: String
let value: String
}
...
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
do {
let root = try decoder.decode(Root.self, from: data)
let countryObjects = root.countryObjects
print(countryObjects)
} catch { print(error) }
(反)序列化 JSON 两次是不必要的昂贵。
推荐阅读
- python - 如何使用 discord.py 检查默认的个人资料图片?
- qt - 如何使用 QT 从 QML 获取数据到 C++?
- c# - 删除引用的行后外键未设置为空
- java - 使用 BPEL 流程时出现 org/eclipse/swt/custom/TableTree 错误?
- c# - 对象属性上的 SelectMany 然后将结果保存回属性会导致 stackoverflow
- azure - 使用 Azure 函数调用的输出 (JSON) 在 ADFv2 中调用存储过程。传递类型,而不是 JSON 字符串?
- python - 大熊猫中的一行选择
- android - Android 的 WebViewClient.shouldInterceptRequest() 仅在第一次调用
- javascript - 在 IE 11 中抑制 Active X 警告“此页面上的 Active X 控件”
- python - 从 Pandas 数据框中的列表中创建元组列表