如何使用 decodable 解析包含动态键的 JSON?

How to parse a JSON containing dynamic keys using decodable?

问题

我目前在解码 JSON 中的通用密钥时遇到问题。我当前的实现接受 3 个键,主要的、次要的、第三个。但是将来我希望 JSON 字典的键是通用的。我已尝试实现本教程中所述的类似方式:https://benscheirman.com/2017/06/swift-json/。不幸的是我无法让它工作,非常欢迎一些帮助。

我的问题与以下问题不同

以下 post 处理不同级别的泛型 "nes":How to deal with completely dynamic JSON responses 因此我的问题比将此问题与 post 以上..

当前JSON

{
  "primary": {
    "color": [3,111,66,1],
    "font": {
      "name": "UniversLTStd-UltraCn",
      "size": "16"
    }
  },
  "secondary": {
    "color": [11,34,56,1],
    "font": {
      "name": "UniversLTStd-UltraCn",
      "size": "16"
    }
  },
  "tertiary": {
    "color": [233,222,211,1],
    "font": {
      "name": "UniversLTStd-UltraCn",
      "size": "16"
    }
  }
}

希望/可能JSON

{
      "SomeKey": {
        "color": [3,111,66,1],
        "font": {
          "name": "UniversLTStd-UltraCn",
          "size": "16"
        }
      },
      "OtherKey": {
        "color": [11,34,56,1],
        "font": {
          "name": "UniversLTStd-UltraCn",
          "size": "16"
        }
      },
      "AnotherKey": {
        "color": [233,222,211,1],
        "font": {
          "name": "UniversLTStd-UltraCn",
          "size": "16"
        }
      }
    }

可以在这里找到可解码的结构:https://pastebin.com/ZYafkDNH

The question

How can I migrate my current code to accepts dynamic keys (at the place of primary, secondary, tertiary..) so I do not have to hard code them in the Base/Root Struct which can be found in Theme now.

您可以尝试将其解析为 [String:Key] 的字典,而不是对键进行硬编码,这样,如果键发生更改,它将被解析,但您必须在应用程序内部执行一些逻辑才能知道哪个值对应于指定的键

let res = try? JSONDecoder().decode([String:Key].self, from: jsonData)


struct Key: Codable {
    let color: [Int]
    let font: Font
}

struct Font: Codable {
    let name, size: String
}

由于您似乎负责 JSON 我建议将结构更改为数组和 type 属性.

[{"type": "primary",
  "appearance": {
    "color": [3,111,66,1],
    "font": {
      "name": "UniversLTStd-UltraCn",
      "size": "16"
      }
    }
  },
  {
  "type": "secondary",
  "appearance": {
    "color": [11,34,56,1],
    "font": {
      "name": "UniversLTStd-UltraCn",
      "size": "16"
      }
    }
  },
  {
  "type": "tertiary",
  "appearance": {
    "color": [233,222,211,1],
    "font": {
      "name": "UniversLTStd-UltraCn",
      "size": "16"
      }
    }
}]

更容易维护。

对应的结构是

struct Theme : Decodable {
    let type : String // could be even a custom enum
    let appearance : Appearance
}

struct Appearance: Decodable {
    let color: [UInt8]
    let font: Font
}

struct Font: Decodable {
    let name, size: String
}

并将JSON解码为[Theme].self

否则,按照 Sh_Khan 的建议,您必须解码字典或编写自定义初始化程序。