json - Swift 4 可解码,直到解码时才知道 key

Swift 4 Decodable 协议(protocol)如何处理包含直到运行时才知道名称的键的字典?例如:

  [
    {
      "categoryName": "Trending",
      "Trending": [
        {
          "category": "Trending",
          "trailerPrice": "",
          "isFavourit": null,
          "isWatchlist": null
        }
      ]
    },
    {
      "categoryName": "Comedy",
      "Comedy": [
        {
          "category": "Comedy",
          "trailerPrice": "",
          "isFavourit": null,
          "isWatchlist": null
        }
      ]
    }
  ]

这里有一个字典数组;第一个有键 categoryNameTrending,而第二个有键 categoryNameComedycategoryName 键的值告诉我第二个键的名称。我如何使用 Decodable 来表达?

最佳答案

关键在于您如何定义 CodingKeys 属性。虽然它最常见的是 enum,但它可以是任何符合 CodingKey 协议(protocol)的东西。要制作动态键,您可以调用静态函数:

struct Category: Decodable {
    struct Detail: Decodable {
        var category: String
        var trailerPrice: String
        var isFavorite: Bool?
        var isWatchlist: Bool?
    }

    var name: String
    var detail: Detail

    private struct CodingKeys: CodingKey {
        var intValue: Int?
        var stringValue: String

        init?(intValue: Int) { self.intValue = intValue; self.stringValue = "\(intValue)" }
        init?(stringValue: String) { self.stringValue = stringValue }

        static let name = CodingKeys.make(key: "categoryName")
        static func make(key: String) -> CodingKeys {
            return CodingKeys(stringValue: key)!
        }
    }

    init(from coder: Decoder) throws {
        let container = try coder.container(keyedBy: CodingKeys.self)
        self.name = try container.decode(String.self, forKey: .name)
        self.detail = try container.decode([Detail].self, forKey: .make(key: name)).first!
    }
}

用法:

let jsonData = """
  [
    {
      "categoryName": "Trending",
      "Trending": [
        {
          "category": "Trending",
          "trailerPrice": "",
          "isFavourite": null,
          "isWatchlist": null
        }
      ]
    },
    {
      "categoryName": "Comedy",
      "Comedy": [
        {
          "category": "Comedy",
          "trailerPrice": "",
          "isFavourite": null,
          "isWatchlist": null
        }
      ]
    }
  ]
""".data(using: .utf8)!

let categories = try! JSONDecoder().decode([Category].self, from: jsonData)

(我将 JSON 中的 isFavourit 更改为 isFavourite,因为我认为这是拼写错误。如果不是这种情况,修改代码很容易)

https://stackoverflow.com/questions/45598461/

相关文章:

javascript - 即使有循环引用,如何将 DOM 节点序列化为 JSON?

json - 如何在 JSONPath 中按字符串过滤?

json - JSON 表示中的链接关系

javascript - 如何使用 Typeahead.js 0.10 一步一步/远程/预取/本地

json - 使用逗号拆分 NSString

javascript - 如何从 AJAX 调用中返回一个数组?

c# - 使用 Nancy 返回包含有效 Json 的字符串

java - 更新 JSONObject 中的元素

php - 从 PHP 中的 JSON POST 读取 HTTP 请求正文的问题

json - bash 中的转义字符(对于 JSON)