iOS 13+ Swift嵌套对象自定义JSON解码器实现方案
iOS 13+ 兼容的嵌套JSON解码方案(依赖父对象type字段)
问题场景
JSON响应包含type字段(值为email或telephone),嵌套的content.attributes结构随type变化,需在解码content时依赖父对象的type值,且需兼容iOS 13+,无法使用iOS 15+的CodableWithConfiguration。
实现步骤
1. 定义类型枚举与属性模型
先明确响应类型和对应属性结构:
// 响应类型枚举 enum ResponseType: String, Codable { case email, telephone } // Email类型对应的属性模型 struct EmailAttributes: Codable { let emailAddress: String let isPrimary: Bool } // Telephone类型对应的属性模型 struct TelephoneAttributes: Codable { let phoneNumber: String let countryCode: String }
2. 定义可解码的ContentResponse枚举
用枚举封装不同类型的属性,通过自定义初始化方法接收父对象的type参数:
enum ContentResponse: Codable { case email(EmailAttributes) case telephone(TelephoneAttributes) // 接收type参数的自定义解码初始化 init(type: ResponseType, from decoder: Decoder) throws { let container = try decoder.singleValueContainer() switch type { case .email: let attrs = try container.decode(EmailAttributes.self) self = .email(attrs) case .telephone: let attrs = try container.decode(TelephoneAttributes.self) self = .telephone(attrs) } } // 编码方法(若需编码可实现,此处省略核心逻辑) func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() switch self { case .email(let attrs): try container.encode(attrs) case .telephone(let attrs): try container.encode(attrs) } } }
3. 父对象Response自定义解码逻辑
在父对象解码时先获取type,再将其传递给ContentResponse完成解码:
struct Response: Codable { let type: ResponseType let content: ContentResponse init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // 优先解码type字段 self.type = try container.decode(ResponseType.self, forKey: .type) // 获取content字段的专属解码器,传递type解码ContentResponse let contentDecoder = container.superDecoder(forKey: .content) self.content = try ContentResponse(type: self.type, from: contentDecoder) } enum CodingKeys: String, CodingKey { case type, content } }
方案说明
- 完全兼容iOS 13+:所有API均为Swift 5.1+(iOS 13对应Swift版本)支持的标准Codable扩展,无系统版本限制。
- 逻辑清晰:父对象先解码关键的
type字段,再通过superDecoder为子对象创建独立解码上下文,将type参数传递给子对象的自定义初始化,实现基于父字段的动态解码。
内容的提问来源于stack exchange,提问作者romainb78
相关产品推荐
相关产品推荐

