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
相关产品推荐
相关产品推荐

