Parsing JSON in swift 4 with nested unkown ids

I am trying to parse a json structure like this:

{
"data": {
    "1": {
        "id": 1, 
        "name": "Bitcoin", 
        "symbol": "BTC", 
        "website_slug": "bitcoin", 
        "rank": 1, 
        "circulating_supply": 17142612.0, 
        "total_supply": 17142612.0, 
        "max_supply": 21000000.0, 
        "quotes": {
            "USD": {
                "price": 6401.53, 
                "volume_24h": 4161310000.0, 
                "market_cap": 109738944996.0, 
                "percent_change_1h": -0.12, 
                "percent_change_24h": -5.11, 
                "percent_change_7d": -1.94
            }
        }, 
        "last_updated": 1531274181
    }, 
    "1027": {
        "id": 1027, 
        "name": "Ethereum", 
        "symbol": "ETH", 
        "website_slug": "ethereum", 
        "rank": 2, 
        "circulating_supply": 100613441.0, 
        "total_supply": 100613441.0, 
        "max_supply": null, 
        "quotes": {
            "USD": {
                "price": 440.618, 
                "volume_24h": 1816230000.0, 
                "market_cap": 44332093270.0, 
                "percent_change_1h": -0.11, 
                "percent_change_24h": -7.03, 
                "percent_change_7d": -4.9
            }
        }, 
        "last_updated": 1531274192
    }, 
.
.
. continues on...

I am having difficulties writing the codable structs in swift:

struct Crypto: Codable{
let data: Coin

struct Coin: Codable{
    let id_num: String

    init(dictionary: [String : Coin]){
        let key = dictionary.keys.first

        self.id_num = key!

    }
    struct CoinInfo: Codable{
        let id: String
        let name: String
    }
}
}

My problem is that the id of each coin is different for each data. E.g. 1 for bitcoin and 1027 for ethereum. I need to get the name, symbol, and percentage changes to display into tableviews. How can i write the structs for this?

2 answers

  • answered 2018-07-11 03:30 rmaddy

    Update your structures as follows:

    struct Crypto: Codable{
        let data: [String: CoinInfo]
    
        struct CoinInfo: Codable{
            let id: Int
            let name: String
        }
    }
    

    After you decode this using:

    let cryptoData = try JSONDecoder().decode(Crypto.self, from: coinData)
    

    you will have a dictionary of CoinInfo in cryptoData.data. The keys will be strings representing the ids.

    Note that the id in CoinInfo is an Int, not a String in order to match the data in JSON.

  • answered 2018-07-11 03:44 tphduy

    I strongly recommend SwiftyJSON for handling son, it is lightweight and flexible framework, you can access json property like this: json["something"].stringValue without afraid of crashing.

    In your cases:

    let dict = json["data"].dictionaryValue
    
    for (id, data) in dict {
        self.id = data["id"]
        self.name = data["name"]
        // ...
    }