swift中嵌套字典API的结构

时间:2018-05-16 07:09:49

标签: ios json swift xcode api

我试图从coinmarketcap API的v2导入JSON数据。我有它使用v1,因为它是一个数组,但新版本是一个字典,我不能让我的结构正确。 我正在使用的API是:https://api.coinmarketcap.com/v2/ticker/?convert=AUD

我的结构设置如下:

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
}

我获取数据的代码是:

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()
}

我获取数据的代码我使用的是与之前使用的API相同的API,但我不认为我正确地构建了我的结构。

提前致谢!

2 个答案:

答案 0 :(得分:2)

您的回复已更改我尝试通过将其转换为字典数组进行配置,您需要将quotes更改为[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()
    }

答案 1 :(得分:1)

data参数中的响应应该是数组而不是字典。您将无法在未定义的键上迭代字典。最好先更新API的响应。

但是,如果您希望继续使用现有的API响应,首先需要将响应转换为数组并使用Decodable结构作为:

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
}

将API块中的数据解析更新为:

    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)")
    }