[英]JSONDecoder parsing incoherence
I went across a problem when decoding a JSON file.我在解码 JSON 文件时遇到了问题。
The file structure is as follows:文件结构如下:
{"grocery":
[
{ "vegetables":
{"quantity":"some",
"compostable":true,
"stockageSite":"string",
"package":"bag"
},
"meats":
{"quantity":"string",
"compostable":true,
"stockageSite":"string",
"package":"box"
},
"site":"string",
"active":true,
"name":"string"
}
]
}
for which I have the following structs我有以下结构
struct Goods: Codable {
var quantity: String
var compostable: Bool
var stockageSite: String
var package: String
}
struct Details: Codable {
var vegetables: Goods
var meats: Goods
var site: String
var active: Bool
var name: String
}
struct Grocery: Codable {
var grocery: [Details]
}
the decoding (do-catch with解码(do-catch with
URLSession.shared.dataTask(with: request){data, response, error in
if let error = error {
print("Error took place: \(error)")
return
}
if let response = response as? HTTPURLResponse {
if response.statusCode != 200{
print("Response HTTP Status code: \(response.statusCode)")
}
}
if let data = data{
let decoder = JSONDecoder()
do {
let jsonParse: Grocery = try decoder.decode(Grocery.self, from: data)
print("parsed \(jsonParse)")
}
catch let jsonError as NSError{
print("Failed \(jsonError)")
}
) parses very well with no errors throwed as long as I remove the "quantity" or "stockage site" or "package" from Goods (-> ie, the ones with string values, exactly as if more than 2 string items doesn't work there). ) 解析得很好,只要我从 Goods 中删除“数量”或“库存站点”或“包装”(-> 即具有字符串值的那些,就好像超过 2 个字符串项目没有在那里工作)。 Otherwise, there's no parsing and the code execution stops there.
否则,没有解析并且代码执行在那里停止。 No error throwed (except in Playgrounds:
没有抛出错误(除了在 Playgrounds 中:
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
The string type is the good one, there are no typos.字符串类型是好的,没有错别字。 The "compostable" (bool) is well recognized.
“可堆肥”(bool)是公认的。
(The same thing happens if I add a string element to "Details" and change my json accordingly.) (如果我将字符串元素添加到“详细信息”并相应地更改我的 json,则会发生同样的事情。)
here are the results printed after correct parsing (whichever of the 3 string elements is removed, so "package" can be parsed correctly):以下是正确解析后打印的结果(删除 3 个字符串元素中的任何一个,因此可以正确解析“包”):
parsed Grocery(grocery: [__lldb_expr_5.Details(vegetables: __lldb_expr_5.Goods(quantity: "some", compostable: true, stockageSite: "string"), meats: __lldb_expr_5.Goods(quantity: "string", compostable: true, stockageSite: "string"), site: "string", active: true, name: "string")])解析的杂货(杂货:[__lldb_expr_5.Details(蔬菜:__lldb_expr_5.Goods(数量:“一些”,可堆肥:真实,stockageSite:“字符串”),肉类:__lldb_expr_5.Goods(数量:“字符串”,可堆肥:真实,库存S : "string"), site: "string", active: true, name: "string")])
and (sometimes! but why?!) the error message printed :和(有时!但为什么?!)打印的错误消息:
Failed Swift.DecodingError.valueNotFound(__lldb_expr_7.Details, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "grocery", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Expected Details but found null instead.", underlyingError: nil))失败 Swift.DecodingError.valueNotFound(__lldb_expr_7.Details, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "grocery", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), _JSONKey(stringValue) : "Index 0", intValue: 0)], debugDescription: "Expected Details but found null 相反。",underlyingError: nil))
just as if the third string element was never found.就像从未找到第三个字符串元素一样。 Would you have a hint of what is going on?
你会知道发生了什么吗?
The Question needs more information but I will guess that the keys in those objects sometimes are missing so here is how you can handle that, by simply using init(from decoder: Decoder)
and giving default values for missing keys using decodeIfPresent
change your Goods
struct to this问题需要更多信息,但我猜这些对象中的键有时会丢失,因此您可以通过简单地使用
init(from decoder: Decoder)
decodeIfPresent
init(from decoder: Decoder)
并使用decodeIfPresent
更改您的Goods
结构为丢失的键提供默认值来处理decodeIfPresent
对此
struct Goods: Codable {
var quantity: String
var compostable: String
var stockageSite: String
private enum CodingKeys: String, CodingKey {
case quantity
case compostable
case stockageSite
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.quantity = try container.decodeIfPresent(String.self, forKey: .quantity) ?? "Empty"
self.compostable = try container.decodeIfPresent(String.self, forKey: .compostable) ?? "Empty"
self.stockageSite = try container.decodeIfPresent(String.self, forKey: .stockageSite) ?? "Empty"
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.