You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中使用async/await异步解码API JSON数据时出现解码错误

问题排查与解决方案

核心问题根源

你遇到的解码失败,是因为API返回的部分条目里ISIN字段为null,但你的Quote结构体中isin被定义为非可选的String类型。Swift的Codable协议要求非可选类型必须对应JSON中的非空值,当遇到null时无法完成解码,直接抛出valueNotFound错误。

错误日志里的Index 3明确指向第4条数据的ISIN字段为null,导致整个数组解码失败。

解决方案步骤

1. 修改结构体字段为可选类型

将Quote中的isin改为可选的String?,允许其接收JSON中的null值:

struct Quote: Codable, Identifiable {
    var id: UUID { return UUID() }
    let code: String
    let exchange: String
    let name: String
    let type: String
    let isin: String? // 改为可选类型
    let price: Double
    let closeDate: String
    let country: String
    let currency: String
    
    private enum CodingKeys: String, CodingKey {
        case code = "Code"
        case exchange = "Exchange"
        case name = "Name"
        case type = "Type"
        case isin = "ISIN"
        case price = "previousClose"
        case closeDate = "previousCloseDate"
        case country = "countryName"
        case currency = "currencyCode"
    }
}

2. 优化错误处理逻辑

你当前用try?吞掉了所有解码错误,导致无法看到具体问题。建议改为do-catch捕获并打印详细错误,方便后续调试:

// 替换原解码代码段
let decoder = JSONDecoder()
do {
    let securities = try decoder.decode([Quote].self, from: data)
    self.searchResults = securities
} catch {
    print("解码详细错误:\(error)")
    self.error = error
    return
}

3. 可选:给空字段设置默认值

如果业务上不希望isin为nil,可以自定义解码方法,给null的ISIN设置默认值(比如空字符串):

struct Quote: Codable, Identifiable {
    var id: UUID { return UUID() }
    let code: String
    let exchange: String
    let name: String
    let type: String
    let isin: String // 保持非可选
    let price: Double
    let closeDate: String
    let country: String
    let currency: String
    
    private enum CodingKeys: String, CodingKey {
        case code = "Code"
        case exchange = "Exchange"
        case name = "Name"
        case type = "Type"
        case isin = "ISIN"
        case price = "previousClose"
        case closeDate = "previousCloseDate"
        case country = "countryName"
        case currency = "currencyCode"
    }
    
    // 自定义解码初始化方法
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        code = try container.decode(String.self, forKey: .code)
        exchange = try container.decode(String.self, forKey: .exchange)
        name = try container.decode(String.self, forKey: .name)
        type = try container.decode(String.self, forKey: .type)
        // 若ISIN为null,默认空字符串
        isin = try container.decodeIfPresent(String.self, forKey: .isin) ?? ""
        price = try container.decode(Double.self, forKey: .price)
        closeDate = try container.decode(String.self, forKey: .closeDate)
        country = try container.decode(String.self, forKey: .country)
        currency = try container.decode(String.self, forKey: .currency)
    }
}

额外检查建议

排查API返回的其他字段是否也存在null的可能(比如previousClose),如果有,同样需要将对应结构体字段改为可选类型或设置默认值,避免后续出现类似解码错误。

内容的提问来源于stack exchange,提问作者SPR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 01:19:51