简体   繁体   English

将 JSON 对象解码为 Swift Dictionary 保留密钥

[英]Decode JSON object to Swift Dictionary keeping keys

Using this code:使用此代码:

import Foundation

let jsonData = """
{
  "equipment": [
    {
      "name": "BigBox",
      "origin": "Customer",
      "type_codes": [
        "XCD",
        "QPR"
      ],
      "category": "Shipping",
      "product_counts": {
        "M": 1,
        "D": 2,
        "W": 1,
        "F": 1
      }
    },
    {
      "name": "LittleBox",
      "origin": "Manufacturer",
      "type_codes": [
        "XCD",
        "DDP"
      ],
      "category": "Storage",
      "product_counts": {
        "W": 3,
        "F": 2
      }
    }
  ]
}
""".data(using: .utf8)!

struct EquipmentListing: Codable {
    let equipment: [Equipment]

    enum CodingKeys: String, CodingKey {
        case equipment
    }
}

struct Equipment: Codable {
    let name: String
    let origin: String
    let typeCodes: [String]
    let category: String
    let productCounts: ProductCounts

    enum CodingKeys: String, CodingKey {
        case name
        case origin
        case typeCodes = "type_codes"
        case category
        case productCounts = "product_counts"
    }
}

struct ProductCounts: Codable {
    let m: Int?
    let d: Int?
    let w: Int?
    let f: Int?

    enum CodingKeys: String, CodingKey {
        case m = "M"
        case d = "D"
        case w = "W"
        case f = "F"
    }
}

let equipmentListing = try! JSONDecoder().decode(EquipmentListing.self, from: jsonData)
print( equipmentListing.equipment[0].productCounts.d )

This works, but has the drawback that the productCounts keyed object is turned into a struct with hardcoded members but there could be dozens of possibilities there and I don't want to have to list them all in the code as Optionals.这有效,但有一个缺点,即productCounts键控对象变成了一个带有硬编码成员的结构,但那里可能有几十种可能性,我不想在代码中将它们全部列为 Optionals。 I want to be able to decode my source JSON so that productCounts comes out as a Dictionary instead of a struct.我希望能够解码我的源 JSON,以便productCounts作为字典而不是结构出现。

Basically, I would like the last line to be this instead:基本上,我希望最后一行是这样的:

print( equipmentListing.equipment[0].productCounts["D"] )

** Bonus points if it's possible to change the keys in productCounts from, eg, D to Dishwasher , M to Microwave , etc. as the source is decoded so that this possible: ** 如果可以将productCounts的键从D更改为DishwasherMMicrowave等,因为源已被解码,以便这可能:

print( equipmentListing.equipment[0].productCounts["Dishwasher"] )

Since you want to map from an arbitrary string to an integer, that's a Dictionary, just as you suggest.由于您想从任意字符串映射到整数,因此正如您所建议的那样,这是一个字典。 You can get rid of the ProductCounts struct and use [String: Int] .您可以摆脱 ProductCounts 结构并使用[String: Int]

struct Equipment: Codable {
    let name: String
    let origin: String
    let typeCodes: [String]
    let category: String
    let productCounts: [String: Int]  // <===

    enum CodingKeys: String, CodingKey {
        case name
        case origin
        case typeCodes = "type_codes"
        case category
        case productCounts = "product_counts"
    }
}

print( equipmentListing.equipment[0].productCounts["D"] )
// Optional(2)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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