【问题标题】:Attempt at utilizing decodable尝试使用可解码
【发布时间】:2020-03-03 06:36:46
【问题描述】:

我正在尝试为收到的 JSON 创建可解码结构,但我不断收到:

keyNotFound(CodingKeys(stringValue: "inquiry_quantity", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "orders", intValue: nil), _JSONKey(stringValue: "Index 0", intValue : 0)], debugDescription: "没有与键 CodingKeys 关联的值...

这是我通过解码器运行的 JSON:

{
    "orders_important": 2,
    "orders_inquiry": 2,
    "orders": [

    {
        "information": {
            "total_price": 12.0,
            "order_stage": "CONFIRMED",
            "total_cases": 333,
            "scanned": false,
            "inquiry": false,
            "foodhub": "shdw.fh1@agg.com",
            "identifier": "GPO00024",
            "delivery_date": "2019-11-04"
        },
        "details": {
            "pack_size": "40#",
            "cases": 333,
            "plu_code": 12434,
            "crop_plan": 1633,
            "commodity": "Conventional Bananas, , 40#"
        }
    },
    {
        "information": {
            "inquiree": "FARMER",
            "total_price": 23.5,
            "order_stage": "INQUIRY",
            "inquiry_quantity": 0,
            "total_cases": 56,
            "scanned": false,
            "inquiry": true,
            "foodhub": "shdw.fh1@agg.com",
            "inquiry_type": "PRICE",
            "identifier": "GPO00027",
            "inquiry_price": 26.5,
            "delivery_date": "2019-11-05",
            "inquiry_details": "You have requested $26.5 per case, instead of $23.5."
        },
        "details": {
            "pack_size": "40#",
            "cases": 12,
            "plu_code": 12434,
            "crop_plan": 1589,
            "commodity": "Conventional Bananas, , 40#"
        }
    },
],
"orders_count": 4
}

我的可解码结构:(编辑:删除初始化)

struct OrderBundle: Decodable{
    let orders_important : Int
    let orders_inquiry:Int
    let orders_count: Int
    let orders: [Order]
}

struct Order: Decodable {
    let inquiry_quantity : Int
    let inquiry_price : Int
    let inquiry_info : String
    let price : Int
    let cropPlan : Int
    let identifier: String
    let deliveryDate : String
    let quantity : Int
    let unit : String
    let status : String
    let destination : String
    let commodity: String

}

最后调用我的解码器:

let orderData = try
                    JSONDecoder().decode(OrderBundle.self, from: data!)
                print(orderData)

我已经在我的 Orders 中使用和不使用 Init 进行了尝试,两种方式我仍然遇到相同的错误。

【问题讨论】:

  • init(json:) 不会被JSONDecoder().decode(OrderBundle.self, from: data!) 调用,你知道吗?您需要使用编码器添加自定义初始化来处理相同的问题。
  • 我刚刚意识到那是行不通的。我该如何编写自定义初始化?我是否必须在自定义初始化中运行另一个解码器?
  • 这里的问题是Order的字段都没有直接出现在json中。它们嵌套在两个子对象中,由"information""details" 键入。您要么需要创建一个OrderInformationOrderDetails 结构,要么需要编写一个自定义初始化程序来解析该数据以直接填充到您的Ordermedium.com/@nictheawesome/…

标签: json swift


【解决方案1】:

主要问题是,如果未提供init(from decoder,则必须将任何字典解码为额外的结构。所以基本上模型的结构一定是

struct OrderBundle: Decodable {
    struct Information : Decodable {
    struct Details : Decodable {

完整的结构如下,许多结构成员必须声明为可选的,inquiryPriceDouble,而不是IntconvertFromSnakeCasesnaked_cased 键转换为 camelCased 结构成员。

struct OrderBundle : Decodable{
    let ordersImportant : Int
    let ordersInquiry : Int
    let ordersCount : Int
    let orders : [Order]
}

struct Order : Decodable {

    let information : Information
    let details : Details

    struct Information : Decodable {
        let inquiryQuantity : Int?
        let inquiryPrice : Double?
        let inquiryInfo : String?
        let price : Int?
        let cropPlan : Int?
        let identifier : String
        let deliveryDate : String
        let quantity : Int?
        let unit : String?
        let status : String?
        let destination : String?
        let commodity: String?
    }

    struct Details : Decodable {
        let packSize : String
        let cases : Int
        let pluCode : Int
        let cropPlan : Int
        let commodity : String
    }
}

以及解码它的代码

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let orderData = try decoder.decode(OrderBundle.self, from: data!)
print(orderData)

【讨论】:

  • 谢谢!我将尝试这个解决方案,然后进一步了解有关解码器初始化和 CodingKeys 的信息。我更好地理解结构。但是,我使用这种方法得到了Type 'OrderBundle' does not conform to protocol 'Decodable',但我看不到发生了什么变化。
  • 请完全使用我的结构并添加convertFromSnakeCase 策略
  • 这很棒。再次感谢@vadian
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-01
  • 1970-01-01
相关资源
最近更新 更多