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

Swift中如何自定义解码含动态类型的API响应?

Swift自定义解码不同类型对象的实现方案

要解决这种由key字段标识object类型的JSON解码问题,核心是在解码包含key和object的结构体时,先获取key的值,再根据它解析对应类型的object。以下是完整的实现代码和关键说明:

修正并完善后的解码代码

struct Response: Decodable {
    let data: [DataItem]
}

struct DataItem: Decodable {
    let key: String
    let object: ObjectType
    
    // 自定义解码逻辑
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // 先解码key字段,确定object的类型
        self.key = try container.decode(String.self, forKey: .key)
        
        // 根据key值分支处理object的解码
        switch self.key {
        case "word":
            let wordValue = try container.decode(String.self, forKey: .object)
            self.object = .word(wordValue)
        case "number":
            let numberValue = try container.decode(Int.self, forKey: .object)
            self.object = .number(numberValue)
        default:
            // 遇到未知key时抛出明确错误,便于调试
            throw DecodingError.dataCorruptedError(
                forKey: .key,
                in: container,
                debugDescription: "无法识别的key类型:\(self.key)"
            )
        }
    }
    
    // 定义JSON字段对应的编码键
    private enum CodingKeys: String, CodingKey {
        case key, object
    }
}

enum ObjectType: Decodable {
    case word(String)
    case number(Int) // 修正原枚举名,与JSON的key值保持一致
}

关键说明

  1. 解码时机选择:必须在DataItem(原代码中的Objects)结构体中实现自定义解码,因为ObjectType的类型依赖于同层级的key字段,单独解码ObjectType时无法获取key的值。
  2. 分支解码逻辑:先解码key,再根据key的取值,将object字段解码为对应类型(字符串/整数),最后创建ObjectType枚举实例。
  3. 错误处理:针对未知的key类型抛出解码错误,避免静默失败,方便排查问题。
  4. 命名一致性:修正枚举成员名为number,与JSON中的key: "number"对应,保持代码语义清晰。

解码使用示例

// 标准格式的JSON字符串(注意原示例JSON的key需要加双引号)
let jsonString = """
{
    "data": [
        {
            "key": "word",
            "object": "hello"
        },
        {
            "key": "number",
            "object": 15
        }
    ]
}
"""

do {
    let data = jsonString.data(using: .utf8)!
    let response = try JSONDecoder().decode(Response.self, from: data)
    
    // 遍历解码结果
    for item in response.data {
        switch item.object {
        case .word(let text):
            print("单词类型:\(text)")
        case .number(let num):
            print("数字类型:\(num)")
        }
    }
} catch {
    print("解码失败:\(error)")
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 06:10:19