简体   繁体   中英

Swift Codable JSON parse error with JSONDecoder

I am trying to handle a JSON with Codable but there's a parsing error when I decode it with JSONDecoder().decode.

{
    "data": [
        {
            "id": "90",
            "symbol": "BTC",
            "name": "Bitcoin",
            "nameid": "bitcoin",
            "rank": 1,
            "price_usd": "50513.75",
            "percent_change_24h": "3.03",
            "percent_change_1h": "-0.50",
            "percent_change_7d": "-9.91",
            "price_btc": "1.00",
            "market_cap_usd": "942710364520.73",
            "volume24": 70745042591.75044,
            "volume24a": 107034995571.4168,
            "csupply": "18662452.00",
            "tsupply": "18662452",
            "msupply": "21000000"
        },
        {
            "id": "80",
            "symbol": "ETH",
            "name": "Ethereum",
            "nameid": "ethereum",
            "rank": 2,
            "price_usd": "4052.44",
            "percent_change_24h": "10.17",
            "percent_change_1h": "-0.78",
            "percent_change_7d": "17.75",
            "price_btc": "0.084812",
            "market_cap_usd": "466734637594.73",
            "volume24": 53134000887.50444,
            "volume24a": 87082811090.79503,
            "csupply": "115173595.00",
            "tsupply": "115173595",
            "msupply": ""
        }
    ],
    "info": {
        "coins_num": 5949,
        "time": 1621022046
    }
}

The json is like above and I coded all my models like below.

class CoinModel: Codable {
    var data: [Coin]?
    var info: CoinInfo?
    
    enum CodingKeys: String, CodingKey {
        case data
        case info
    }
}

class CoinInfo: Codable {
    var coinsNum: Int?
    var time: TimeInterval?
    
    enum CodingKeys: String, CodingKey {
        case coinsNum = "coins_num"
        case time = "time"
    }
}
class Coin: Codable{
    var csupply: String?
    var id: String?
    var marketCapUsd: String?
    var msupply: Int?
    var name: String?
    var nameid: String?
    var percentChange1h: String?
    var percentChange24h: String?
    var percentChange7d: String?
    var priceBtc: String?
    var priceUsd: String?
    var rank: Int?
    var symbol: String?
    var tsupply: Int?
    var volume24: Double?
    var volume24a: Double?

    enum CodingKeys: String, CodingKey {
        case csupply = "csupply"
        case id = "id"
        case marketCapUsd = "market_cap_usd"
        case msupply = "msupply"
        case name = "name"
        case nameid = "nameid"
        case percentChange1h = "percent_change_1h"
        case percentChange24h = "percent_change_24h"
        case percentChange7d = "percent_change_7d"
        case priceBtc = "price_btc"
        case priceUsd = "price_usd"
        case rank = "rank"
        case symbol = "symbol"
        case tsupply = "tsupply"
        case volume24 = "volume24"
        case volume24a = "volume24a"
    }
}

And my network function work like below.

URLSession.shared.dataTask(with: url) { (data, response, error) in
    guard error == nil else {
        completion(.failure(error!))
        return
    }
    
    guard let data = data else {
        completion(.failure(error ?? NSError()))
        return
    }
    
    let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String: Any]
    
    guard let model = try? JSONDecoder().decode(CoinModel.self, from: data) else {
        completion(.success([]))
        return
    }
    
    completion(.success(model.data ?? []))
    
}.resume()

As I said before, json object is not nil and I got like below.

[({
    csupply = "435032301.00";
    id = 33285;
    "market_cap_usd" = "435337535.24";
    msupply = "";
    name = "USD Coin";
    nameid = "usd-coin";
    "percent_change_1h" = "0.01";
    "percent_change_24h" = "0.19";
    "percent_change_7d" = "0.16";
    "price_btc" = "0.000023";
    "price_usd" = "1.00";
    rank = 100;
    symbol = USDC;
    tsupply = 435032301;
    volume24 = "11520659193.03477";
    volume24a = "13684311331.83874";
}
)
, "info": {
    "coins_num" = 5952;
    time = 1621160044;
}]

I can handle the JSON with JSONSerialization but I could not find any reason for parse error in the JSONDecoder way. I think I did not see the problem. Thanks for any advice and helps.

Edit:

I solved it with several changes in my Codable class, I made a mistake when I describing model for id , csupply and etc.

var csupply: String?
var msupply: String?
var tsupply: String?

You have several mistakes on defining object. For example you have defined id , msupply is a integer but they are string. You have defined the volume24 and volume24a is string but they are not. You need to fix all of these probably thats why you can't parse it.

All wrong defined parameters are id , mSupply , volume24 , volume24a , tSupply for coin object and for the info object you need to convert time to Int aswell.

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