简体   繁体   English

JSONDecoder 解析不连贯

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM