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

Swift解码API数据时遇字段缺失/为空如何避免崩溃?

解决Swift Decodable中字段缺失导致的解码失败问题

我从API获取数据并解码到如下WatchProvider结构体:

struct WatchProvider: Identifiable, Decodable {
    let id = UUID()
    let link: String?
    let rent: [WatchProviderDetails]?
    let buy: [WatchProviderDetails]?
    let flatrate: [WatchProviderDetails]?
    
    enum CodingKeys: String, CodingKey {
        case link
        case rent
        case buy
        case flatrate
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        link = try container.decodeIfPresent(String.self, forKey: .link)
        rent = try container.decode([WatchProviderDetails].self, forKey: .rent)
        buy = try container.decode([WatchProviderDetails].self, forKey: .buy)
        flatrate = try container.decode([WatchProviderDetails].self, forKey: .buy)
    }
}

但API返回的数据中,rent、flatrate等字段时常缺失或为空,解码时会抛出如下错误:

sink error: keyNotFound(CodingKeys(stringValue: "rent", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "results", intValue: nil), CodingKeys(stringValue: "US", intValue: nil)], debugDescription: "No value associated with key CodingKeys(stringValue: "rent", intValue: nil) ("rent").", underlyingError: nil))

核心修复方案

你当前的问题根源在于手动实现解码初始化方法时,对rent、buy、flatrate使用了decode(_:forKey:)方法——这个方法强制要求目标字段必须存在,否则直接抛出解码错误。要实现字段缺失时忽略并返回nil,需改用decodeIfPresent(_:forKey:)方法。

另外注意代码中的笔误:flatrate字段解码时误用了.buy的Key,会导致flatrate始终读取buy的数据,需修正为.flatrate。

修改后的初始化方法如下:

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    link = try container.decodeIfPresent(String.self, forKey: .link)
    // 改用decodeIfPresent,字段缺失时自动返回nil
    rent = try container.decodeIfPresent([WatchProviderDetails].self, forKey: .rent)
    buy = try container.decodeIfPresent([WatchProviderDetails].self, forKey: .buy)
    // 修正flatrate对应的CodingKey
    flatrate = try container.decodeIfPresent([WatchProviderDetails].self, forKey: .flatrate)
}

额外优化:使用自动合成解码逻辑

如果你的结构体所有需要解码的字段都是可选类型,且CodingKeys与字段名完全匹配,可以直接移除手动实现的init(from decoder:),让Swift自动合成解码逻辑。自动合成的实现会默认对可选字段使用decodeIfPresent,无需额外代码,更简洁且不易出错。

优化后的结构体代码:

struct WatchProvider: Identifiable, Decodable {
    let id = UUID()
    let link: String?
    let rent: [WatchProviderDetails]?
    let buy: [WatchProviderDetails]?
    let flatrate: [WatchProviderDetails]?
    
    enum CodingKeys: String, CodingKey {
        case link
        case rent
        case buy
        case flatrate
    }
    // 移除手动解码实现,依赖Swift自动合成的逻辑
}

这样无论API返回的字段是否存在,可选类型的字段都会被自动处理为nil,不会中断整个解码流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 10:10:11