【问题标题】:Swift Codable JSON parse error with JSONDecoder使用 JSONDecoder 的 Swift Codable JSON 解析错误
【发布时间】:2021-08-05 21:03:06
【问题描述】:

我正在尝试使用 Codable 处理 JSON,但是当我使用 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
    }
}

json 和上面一样,我编写了所有模型,如下所示。

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

我的网络功能如下所示。

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

正如我之前所说,json 对象不是 nil,我得到如下所示。

[({
    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;
}]

我可以使用 JSONSerialization 处理 JSON,但我找不到任何以 JSONDecoder 方式解析错误的原因。我想我没有看到问题。感谢您的任何建议和帮助。

编辑:

我在我的 Codable 类中进行了几处更改解决了这个问题,我在描述 idcsupply 等的模型时犯了一个错误。

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

【问题讨论】:

  • 不要使用try ? - 这会丢弃可能对您有帮助的错误。在catch 块中使用do/try/catchprint(error)
  • 嘿 @Paulw11 我忘记使用 catch 错误块,我现在正在使用,我会更新问题
  • volume24volume24a 不是 Strings
  • 解码时还有一种原生方式将snake_case转换为camelCase,无需定义你的编码键。见developer.apple.com/documentation/foundation/jsondecoder/…
  • 如果他们改变了 API,你甚至不会注意到它。使用非可选值你会得到一个错误(当然如果你不忽略它)。

标签: ios json swift codable


【解决方案1】:

你在定义对象时有几个错误。例如,您定义了idmsupply 是整数,但它们是字符串。您已经定义了 volume24volume24a 是字符串,但它们不是。您需要解决所有这些问题,这可能就是您无法解析它的原因。

所有错误定义的参数都是idmSupplyvolume24volume24atSupply,用于硬币对象和info对象,您还需要将time转换为Int

【讨论】:

  • 嘿@Alihan,感谢您的回答,我将模型更改为 id 为String,卷为Double,但我收到了格式不正确的错误。
  • 你好@eemrah 我已经用错误定义参数的完整列表更新了我的问题,你能修复所有这些参数并重试吗?
  • 嘿@Alihan,感谢您的回答,我会更正您的答案,实际上在您第一次回答之后,我发现csupply 和其他供应变量完全错了。我在他们的定义上犯了一个错误,并且已经改变了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-28
  • 1970-01-01
  • 1970-01-01
  • 2020-01-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多