Ошибка в парсинге

json

#1

Здравствуйте. Помогите пожалуйста разобраться с парсингом. Беру данные криптовалют с этого сайта https://coinmarketcap.com/api/ Ответ с сервера приходит такой:

data”: [
{

        "id": 1,
        "name": "Bitcoin",
        "symbol": "BTC",
        "slug": "bitcoin",
        "num_market_pairs": 8938,
        "date_added": "2013-04-28T00:00:00.000Z",

        "tags": [
            "mineable",
            "pow",
            "sha-256",
            "store-of-value",
            "state-channels"
        ],
        "max_supply": 21000000,
        "circulating_supply": 18478475,
        "total_supply": 18478475,
        "platform": null,
        "cmc_rank": 1,
        "last_updated": "2020-09-03T11:31:33.000Z",
        "quote": {
            "USD": {
                "price": 11273.4407683,
                "volume_24h": 25364037841.8901,
                "percent_change_1h": -0.600125,
                "percent_change_24h": -2.18778,
                "percent_change_7d": -0.96201,
                "market_cap": 208315993401.01236,
                "last_updated": "2020-09-03T11:31:33.000Z"
            }
        }
    }

]

Структура json

struct Response: Decodable {

var data: [CryptoData]

}

struct CryptoData: Decodable {

var id: Int
var name: String
var symbol: String
var slug: String
var max_supply: Int?
var total_supply: QuantumValue
var rank: Int
var last_updated: String

var quote: QuoteDetails

enum CodingKeys: String, CodingKey {
    
    case id
    case name
    case symbol
    case slug
    case max_supply
    case total_supply
    case rank = "cmc_rank"
    case last_updated
    case quote
}

}

struct QuoteDetails: Decodable {

var USD: QuoteUSD

}

struct QuoteUSD: Decodable {

var price: Double
var dailyVolume: Double
var percent_change_1h: Double
var percent_change_24h: Double
var percent_change_7d: Double
var market_cap: Double
var last_updated: String

enum CodingKeys: String, CodingKey {
    case price
    case dailyVolume = "volume_24h"
    case percent_change_1h
    case percent_change_24h
    case percent_change_7d
    case market_cap
    case last_updated
}

}

//Использую QuantumValue т.к. значение приходит и в Int, и Double

enum QuantumValue: Decodable {

case int(Int), double(Double)

init(from decoder: Decoder) throws {
    if let int = try? decoder.singleValueContainer().decode(Int.self) {
        self = .int(int)
        return
    }

    if let double = try? decoder.singleValueContainer().decode(Double.self) {
        self = .double(double)
        return
    }

    throw QuantumError.missingValue
}

enum QuantumError:Error {
    case missingValue
}

}

Запрос:

class CurrencyProvider {

func loadData() {
    
    guard let url = URL(string: "https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest") else {
        
        print("Wrong URL.")
        return
    }
    
    let finalURL = url
    var request = URLRequest(url: finalURL)
    request.addValue("c972ac08-519e-47e5-8cd8-23e6230289f3", forHTTPHeaderField: "X-CMC_PRO_API_KEY")
    
    let dataTask = URLSession.shared.dataTask(with: request) { (data, responce, error) in
        
        if let jsonData = data {
            
            do {
                
                let cryptoData = try JSONDecoder().decode(Response.self, from: jsonData)
                print(cryptoData)
            }
            
            catch {
                
                print(error)
            }
        }
    }
    dataTask.resume()
}

}

Выходит следующая ошибка: valueNotFound(Swift.Double, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: “data”, intValue: nil), _JSONKey(stringValue: “Index 67”, intValue: 67), CodingKeys(stringValue: “quote”, intValue: nil), CodingKeys(stringValue: “USD”, intValue: nil),

Подскажите пожалуйста в чем может быть ошибка?


#2

мне кажется, что у Вас здесь проблема, вы не добираетесь до данных внутри…

Попробуйте в инициализаторе прописать структуру.

init (from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self, forKey: .quote)
let USDContainer = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .USD)
self.price = try USDContainer.decode(String.self, forKey: .price)
и тд.
}


#3

Спасибо за помощь! Оказалось что проблема была в том, что неправильно указал типы. percentChangeIn7d должен был быть опционалом, а maxSupply не Int, а Double?