Swift 4 Decodable with keys not known until decoding time

Viewed 17317

How does the Swift 4 Decodable protocol cope with a dictionary containing a key whose name is not known until runtime? For example:

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

Here we have an array of dictionaries; the first has keys categoryName and Trending, while the second has keys categoryName and Comedy. The value of the categoryName key tells me the name of the second key. How do I express that using Decodable?

3 Answers

Here's what I eventually came up for this json:

let json = """
{
    "BTC_BCN":{
        "last":"0.00000057",
        "percentChange":"0.03636363",
        "baseVolume":"47.08463318"
    },
    "BTC_BELA":{
        "last":"0.00001281",
        "percentChange":"0.07376362",
        "baseVolume":"5.46595029"
    }
}
""".data(using: .utf8)!

We make such a structure:

struct Pair {
    let name: String
    let details: Details

    struct Details: Codable {
        let last, percentChange, baseVolume: String
    }
}

then decode:

if let pairsDictionary = try? JSONDecoder().decode([String: Pair.Details].self, from: json) {
    
    var pairs: [Pair] = []
    for (name, details) in pairsDictionary {
        let pair = Pair(name: name, details: details)
        pairs.append(pair)
    }
    
    print(pairs)
}

It is also possible to call not pair.details.baseVolume, but pair.baseVolume:

struct Pair {
    ......
    var baseVolume: String { return details.baseVolume }
    ......

Or write custom init:

struct Pair {
    .....
    let baseVolume: String
    init(name: String, details: Details) {
         self.baseVolume = details.baseVolume
    ......
Related