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

Swift解析JSON时如何根据同层级type参数动态确定body对象类型

Swift 同层级字段动态类型解码实现方案

核心思路是自定义Decodable初始化逻辑,先读取同层级type字段的取值,再按需将body解码为对应强类型结构体,全程使用强类型约束,无需将属性设为可选。

步骤1:定义统一承载Body类型的关联值枚举

由于Swift是强类型语言,body字段需要有明确的类型声明,使用带关联值的枚举可以同时承载两种不同的Body结构体,保留强类型特性:

enum BodyType: Decodable {
    case one(OneBody)
    case two(TwoBody)
}

步骤2:自定义MyObject的解码逻辑

重写init(from decoder: Decoder)方法,先解码当前层级的type字段,再根据type值选择对应的结构体类型解码body:

struct MyObject: Decodable {
    let type: String
    let body: BodyType
    
    // 指定当前层级的解码键
    enum CodingKeys: String, CodingKey {
        case type, body
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // 先解码同层级的type字段
        type = try container.decode(String.self, forKey: .type)
        
        // 根据type值动态选择body的解码类型
        switch type {
        case "one":
            body = .one(try container.decode(OneBody.self, forKey: .body))
        case "two":
            body = .two(try container.decode(TwoBody.self, forKey: .body))
        default:
            throw DecodingError.dataCorruptedError(
                forKey: .type,
                in: container,
                debugDescription: "未知的type取值:\(type)"
            )
        }
    }
}

步骤3:保留两个强类型Body结构体定义

无需修改已经定义好的两个强类型结构体,所有属性保持非可选:

struct OneBody: Decodable {
    let one: Int
}

struct TwoBody: Decodable {
    let two: Int
    let twoData: String
}

调用测试

使用修正后的合法JSON(去掉原示例中的省略占位符)进行解码测试:

let sampleData = Data("""
[
  {
    "type": "one",
    "body": {
      "one": 1
    }
  },
  {
    "type": "two",
    "body": {
      "two": 2,
      "twoData": "two"
    }
  }
]
""".utf8)

do {
    let result = try JSONDecoder().decode([MyObject].self, from: sampleData)
    // 遍历结果时通过switch枚举分支获取对应强类型实例
    for item in result {
        switch item.body {
        case .one(let oneBody):
            print("解析到OneBody类型,one字段值:\(oneBody.one)")
        case .two(let twoBody):
            print("解析到TwoBody类型,two字段值:\(twoBody.two),twoData字段值:\(twoBody.twoData)")
        }
    }
} catch {
    print("解码出错:\(error.localizedDescription)")
}

方案说明

  • 所有解析后的属性均为非可选强类型,不存在松散的可选值校验问题
  • 解码逻辑在MyObject内部完成,外部调用时和普通Codable解析无差异
  • 后续如果新增type类型,只需要在BodyType枚举新增对应case,同时在switch分支补充解码逻辑即可,扩展性好
  • 遇到未定义的type值会主动抛出解码错误,避免静默解析失败的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:27:42