将JSON对象解码为Swift字典并保留密钥

时间:2019-11-29 21:36:34

标签: json swift

使用此代码:

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 )

这有效,但是缺点是productCounts键对象被转换为带有硬编码成员的结构,但是那里可能有数十种可能性,我不想在代码中列出它们作为可选。我希望能够对我的源JSON进行解码,以使productCounts成为字典而不是结构。

基本上,我希望最后一行改为:

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

**如果可以将productCounts中的键从D更改为Dishwasher,将M更改为Microwave等,则奖励积分。因为对源进行了解码,所以可以做到这一点:

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

1 个答案:

答案 0 :(得分:0)

由于您希望将任意字符串映射为整数,因此就像您建议的那样,这就是字典。您可以摆脱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)