структура для вложенного словаря API в Swift - PullRequest
0 голосов
/ 16 мая 2018

Я пытаюсь импортировать данные JSON из v2 API coinmarketcap. Я работал с 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()
}

Мой код для извлечения данных, который я использовал, использовался так же, как и ранее, который работал с v1 API, однако я не думаю, что сделал свою структуру правильно.

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Ваш ответ в параметре 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)")
    }
0 голосов
/ 16 мая 2018

Ваш ответ изменен. Я пытаюсь настроить его, преобразовав его в массив словаря. Вам нужно изменить 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()
    }
...