I need to decode a JSON formatted like this:
{
"rates": {
"btc": {
"name": "Bitcoin",
"unit": "Ƀ",
"value": 0,
"type": "crypto"
},
"eth": {
"name": "Ether",
"unit": "Ξ",
"value": 29.658,
"type": "crypto"
},
"bch": {
"name": "Bitcoin Cash",
"unit": "BCH",
"value": 12.3,
"type": "crypto"
},
"ltc": {
"name": "Litecoin",
"unit": "Ł",
"value": 108.219,
"type": "crypto"
}...}
I currently get the data like this which I am not happy with:
import Foundation
class CGExchange {
static let shared = CGExchange()
var defaultCurrency = UserDefaults.standard.value(forKey: "DefaultCurrency")!
struct Rates: Codable {
let rates: Currency
}
struct Exchange: Codable {
let name: String
let value: Double
let unit: String
}
struct Currency: Codable {
let btc: Exchange
let eth: Exchange
let bch: Exchange
let ltc: Exchange
let usd: Exchange
let aed: Exchange
let ars: Exchange
let aud: Exchange
let bdt: Exchange
let bhd: Exchange
let bmd: Exchange
let brl: Exchange
let cad: Exchange
let chf: Exchange
let clp: Exchange
let cny: Exchange
let czk: Exchange
let dkk: Exchange
let eur: Exchange
let gbp: Exchange
let hkd: Exchange
let huf: Exchange
let idr: Exchange
let ils: Exchange
let inr: Exchange
let jpy: Exchange
let krw: Exchange
let kwd: Exchange
let lkr: Exchange
let mmk: Exchange
let mxn: Exchange
let myr: Exchange
let nok: Exchange
let nzd: Exchange
let php: Exchange
let pkr: Exchange
let pln: Exchange
let rub: Exchange
let sar: Exchange
let sek: Exchange
let sgd: Exchange
let thb: Exchange
let `try`: Exchange
let twd: Exchange
let vef: Exchange
let zar: Exchange
let xdr: Exchange
let xag: Exchange
let xau: Exchange
}
var exchangeData = [Rates]()
func getData(arr: Bool, completion: @escaping (Bool) -> ()) {
/// alamofire / urlsession request
let urlJSON = "https://api.coingecko.com/api/v3/exchange_rates"
guard let url = URL(string: urlJSON) else { return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
do {
// let currencies = try JSONDecoder().decode(Currency.self, from: data)
let exchanges = try JSONDecoder().decode(Rates.self, from: data)
self.exchangeData = [exchanges]
print(self.exchangeData)
completion(arr)
} catch let jsonErr {
print("error serializing json: \(jsonErr)")
}
}.resume()
}
func refresh(completion: () -> ()) {
defaultCurrency = UserDefaults.standard.string(forKey: "DefaultCurrency")!
completion()
}
}
The problem is I only need the values from 3 of the titles held in "rates" But that depends on a UserDefaults Value determined by the users choice. IE, If the user chooses GBP as their defaultCurrency, I need only to get let gbp from the struct currency, but it is awkward to get the value, as I can't change it. i.e. In my DataViewController to get the data I do let exchangeRate = CGExchange.shared.exchangeData[0].rates.gbp.value
but ideally I need the struct to change based on what the default currency is. I.e. let exchangeRate = CGExchange.shared.exchangeData[0].rates.defaultCurrency.value
But I am struggling to find out how I would do that. If I could make a struct with values that could change such as:
struct Currency: Codable {
let dc: Exchange
let sc: Exchange
let tc: Exchange
enum CodingKeys: String, CodingKey {
case dc = "\(defaultCurrency)"
case sc = "\(secondCurrency)"
case tc = "\(currency)"
}
}
That is basically what I need but it says: 'Raw value for enum case must be a literal'
Any suggestions? Thank you.