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

如何使用Swift Codable解码data字段可为字典或数组的JSON

Codable 兼容单字典/数组字段解码方案

前置修正

你当前定义的Data结构体和Foundation框架原生Data类型重名,建议修改为ItemData等不冲突的命名,避免编译异常:

struct ItemData: Codable {
    let id: Int
}

方案1:统一转换为数组存储(推荐)

不管返回的是单个字典还是数组,都统一解析为数组,单个字典自动转为长度为1的数组,业务侧无需额外判断类型:

struct Item: Codable {
    let data: [ItemData]
    
    enum CodingKeys: String, CodingKey {
        case data
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // 优先尝试解析为数组
        if let dataArray = try? container.decode([ItemData].self, forKey: .data) {
            self.data = dataArray
            return
        }
        // 解析数组失败则尝试解析为单个对象,包装为数组
        if let singleData = try? container.decode(ItemData.self, forKey: .data) {
            self.data = [singleData]
            return
        }
        // 都不匹配则抛出解码错误
        throw DecodingError.dataCorruptedError(
            forKey: .data,
            in: container,
            debugDescription: "data字段既不是ItemData类型也不是ItemData数组类型"
        )
    }
}

方案2:保留单值/数组的类型差异

如果业务需要明确区分返回的是单个值还是数组,可以用枚举包装两种情况:

// 定义兼容单值/数组的枚举类型
enum MultiTypeData: Codable {
    case single(ItemData)
    case array([ItemData])
    
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let single = try? container.decode(ItemData.self) {
            self = .single(single)
            return
        }
        if let array = try? container.decode([ItemData].self) {
            self = .array(array)
            return
        }
        throw DecodingError.dataCorruptedError(
            in: container,
            debugDescription: "无法解析为ItemData单值或数组"
        )
    }
    
    // 如需支持编码可实现encode方法
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        switch self {
        case .single(let item):
            try container.encode(item)
        case .array(let items):
            try container.encode(items)
        }
    }
}

// Item结构定义
struct Item: Codable {
    let data: MultiTypeData
}

内容的提问来源于stack exchange,提问作者Игорь Сазонов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 02:54:05