Home > Blockchain >  Decoding JSON structure in Swift when parent name varies?
Decoding JSON structure in Swift when parent name varies?

Time:01-04

I am making an API call which returns the following JSON structure (price info about various cryptocurrencies):

{
  "bitcoin": {
    "gbp": 34532
  },
  "ethereum": {
    "gbp": 2789.08
  }
}

The struct I am using to decode this JSON looks like this:

struct Coin: Codable {
    let gbp: Double

    enum CodingKeys: String, CodingKey {
        case gbp
    }
}

The JSON is not being decoded because the parent of each JSON element returned is the name of a cryptocurrency, but this will change depending on what call is made. As the name always changes, I am not sure how to create a variable in the struct to map each parent. E.g. for this example I could make a struct like this:

struct AllCoins: Codable {
    let bitcoin, ethereum: Coin
}

This will decode this specific example, but if I fetch other coins it will not work because the String names are different, so they will not match up. I am sure I am missing something simple here, but does anyone know how I can go about solving this issue?

CodePudding user response:

If the name can be any arbitrary string, you want to decode a [String: Coin] dictionary. As long as Coin is Codable, [String: Coin] is also Codable.

CodePudding user response:

I regard the effort to decode the JSON with Codable higher than with traditional JSONSerialization. As long as the structure is always

{"<name>":
   {"<base>": <value>}
}

you can decode any currency and any base with this code, the result is an array of Coin

let jsonString = """
{
  "bitcoin": {
    "gbp": 34532
  },
  "ethereum": {
    "gbp": 2789.08
  }
}
"""

struct Coin {
    let name : String
    let base : String
    let value : Double
}

var coins = [Coin]()

do {
    let result = try JSONSerialization.jsonObject(with: Data(jsonString.utf8)) as! [String:[String:Double]]
    coins = result.compactMap{ key, rate in
        guard let base = rate.keys.first else { return nil }
        return Coin(name: key, base: base, value: rate[base]!)
    }
    print(coins)
} catch {
    print(error)
}
  •  Tags:  
  • Related