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

Swift Codable如何解码带type标识的扁平化自类型JSON

实现方案

核心逻辑是先读取根层级的type字段匹配对应的解析类型,再直接用根解码器解析对应实体的字段,无需嵌套payload层。


步骤1:定义业务实体类型

所有需要解析的结构都遵循Codable协议,只声明自身需要的业务字段即可:

// 对应type=row的结构
struct Row: Codable {
    let title: String
    let subtitle: String
}

// 可扩展其他type对应的结构,示例:
struct Banner: Codable {
    let imgUrl: String
    let jumpLink: String
}

步骤2:定义type字段映射枚举

用来关联type字段的取值和对应解析类型:

enum ContentType: String, Codable {
    case row
    case banner
    // 新增type时在此处扩展对应枚举值
}

步骤3:自定义通用解码包装类

在自定义解码逻辑中先读取type,再匹配对应类型解析全量JSON:

enum UniversalContent: Codable {
    case row(Row)
    case banner(Banner)
    // 新增类型时在此处扩展对应case

    init(from decoder: Decoder) throws {
        // 先读取根容器的type字段
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let type = try container.decode(ContentType.self, forKey: .type)
        
        // 根据type匹配对应类型,直接传入根解码器解析
        switch type {
        case .row:
            self = .row(try Row(from: decoder))
        case .banner:
            self = .banner(try Banner(from: decoder))
        }
    }

    enum CodingKeys: String, CodingKey {
        case type
    }
}

这里直接将根解码器传给业务实体解析是完全可行的,JSONDecoder默认会忽略实体未声明的type字段,完美适配扁平化JSON结构。

步骤4:使用示例

let jsonData = 你的JSON数据
let result = try JSONDecoder().decode(UniversalContent.self, from: jsonData)

// 解析完成后取值
switch result {
case .row(let row):
    print(row.title, row.subtitle)
case .banner(let banner):
    print(banner.imgUrl)
}

如果业务场景需要频繁新增类型,也可以基于协议注册的方式实现自动匹配,不需要每次修改枚举,上述写法是小体量业务下最简洁易维护的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 09:18:01