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

如何使用Swift Decodable处理API返回类型不一致的JSON解码问题

解决方案

你可以通过实现可复用的泛型属性包装器来解决该问题,无需手动编写整个结构体的解码逻辑,仅需对需要兼容多类型的字段做标记即可。

首先定义泛型属性包装器:

@propertyWrapper
struct FlexibleArray<Element: Decodable>: Decodable {
    var wrappedValue: [Element]
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        // 优先尝试解码为数组格式
        if let arrayResult = try? container.decode([Element].self) {
            wrappedValue = arrayResult
            return
        }
        // 数组解码失败则尝试解码为单个元素,包装为数组返回
        if let singleResult = try? container.decode(Element.self) {
            wrappedValue = [singleResult]
            return
        }
        // 两种格式都不匹配时抛出解码错误
        throw DecodingError.dataCorrupted(DecodingError.Context(
            codingPath: decoder.codingPath,
            debugDescription: "Expected type either [\(Element.self)] or \(Element.self)"
        ))
    }
    
    // 支持默认值初始化(可选)
    init(wrappedValue: [Element]) {
        self.wrappedValue = wrappedValue
    }
}

修改你的Movie结构体,仅需对需要兼容的director字段添加属性包装器标记:

struct Movie: Decodable {
    let title: String
    let cast: [String]
    @FlexibleArray var director: [String]
}

该方案的优势:

  • 侵入性极低,不需要修改原有结构体的其他属性逻辑,也不需要编写全局的解码规则
  • 可复用性强,所有需要兼容「单元素/数组」两种返回格式的字段都可以直接加@FlexibleArray标记使用,支持所有遵守Decodable协议的元素类型
  • 外部使用无感知,标记后的属性对外暴露的依然是标准数组类型,不需要额外做类型转换

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 15:06:08