简体   繁体   中英

struct for nested dictionary API in swift

i'm trying to import JSON data from the v2 of coinmarketcap API. I had it working with v1 as it was an array, however the new version is a dictionary and i cant quite get my struct correct. The API im using is : https://api.coinmarketcap.com/v2/ticker/?convert=AUD

My struct is set up as below:

struct Coin: Decodable {
private enum CodingKeys: String, CodingKey {
    case id = "rank", symbol, name, priceAUD = "quotes"
}
var id: String
var symbol : String
var name : String
var priceAUD : quoteStruct

}

struct quoteStruct{
    let aud : priceStruct
}

struct priceStruct{
    let price : String
}

My code for fetching the data is:

var coins = [Coin]()

func getCoinData() {
    let jsonURL = "https://api.coinmarketcap.com/v2/ticker/?convert=AUD"
    let url = URL(string: jsonURL)

    URLSession.shared.dataTask(with: url!) { [unowned self] (data, response, error) in
        guard let data = data else { return }
        do {
            self.coins = try JSONDecoder().decode([Coin].self, from: data)
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }

        } catch {
            print("Error is : \n\(error)")
        }
        }.resume()
}

My code for fetching the data i have used the same as previously which worked with v1 of the API, however i don't think i made my struct correctly.

Thanks in advance!

Your response Changed i try to configure it by converting it to array of dictionary you will need to change quotes to be [String:priceStruct ]

struct Coin: Decodable {
    private enum CodingKeys: String, CodingKey {
        case id,rank,symbol, name, priceAUD = "quotes"
    }
    var id: Int
    var rank: Int
    var symbol : String
    var name : String
    var priceAUD : [String: priceStruct]

}

struct priceStruct : Decodable{
    let price : Double
}

 func getCoinData() {
         var coins = [Coin]()
        let jsonURL = "https://api.coinmarketcap.com/v2/ticker/?convert=AUD"
        let url = URL(string: jsonURL)

        URLSession.shared.dataTask(with: url!) { [unowned self] (data, response, error) in
            guard let data = data else { return }
            do {
                 if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any], let resultData = json["data"]  as? [String:Any] {

                     let dataObject = try JSONSerialization.data(withJSONObject: resultData.values.map({$0})  , options: .prettyPrinted)
                    coins = try JSONDecoder().decode([Coin].self, from: dataObject)
                    print(coins.count)

                  }



            } catch {
                print("Error is : \n\(error)")
            }
            }.resume()
    }

You response in data parameter should be an array rather than a dictionary. You will not be able to iterate a dictionary over undefined keys. It would be good to get your response of API updated first.

But, If you wish to continue with the existing API response, first you need to convert your response in an array and use your Decodable structs as:

struct Coin: Decodable {
    var id: String
    var symbol : String
    var name : String
    var priceAUD : QuoteStruct

    private enum CodingKeys: String, CodingKey {
        case id = "rank", symbol, name, priceAUD = "quotes"
    }
}

struct QuoteStruct: Decodable {
    let aud : PriceStruct
}

struct PriceStruct: Decodable {
    let price : String
}

Update your data parsing in API block as:

    guard let responseData = data else { return }
    do {
        let json = try? JSONSerialization.jsonObject(with: responseData, options: [])
        if let jsonData = json as? [String: Any], let dataObject = jsonData["data"] as? [Int: Any] {
            let coinArray = dataObject.map { $0.1 }

            if let jsonData = try? JSONSerialization.data(withJSONObject: coinArray, options: .prettyPrinted) {
                coins = try JSONDecoder().decode([Coin].self, from: jsonData)
                DispatchQueue.main.async {
                    self.tableView.reloadData()
                }
            }
        }
    } catch {
        print("Error is : \n\(error)")
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM