Swift 4 Decodable处理包含多种类型的JSON数组
刚好之前做项目时遇到过一模一样的场景!用Swift 4+的Decodable处理混合类型数组,最靠谱的方式就是用枚举来封装不同的模型,通过数据里的标识字段(比如你JSON里的type)来判断该解析成哪种类型。下面给你一步步讲怎么实现:
1. 先定义具体的模型结构
首先把Member和ImageMedium这两个基础模型写好,各自遵守Decodable协议,对应它们的专属字段:
struct Member: Decodable { let id: String // 这里根据你的实际业务需求添加Member的其他字段,比如name、avatarUrl等 // 如果你需要处理像`owner-id`这种蛇形命名的字段,后面可以用解码器的策略自动转换 } struct ImageMedium: Decodable { let id: String // 同样添加ImageMedium的专属字段,比如imageUrl、width、height等 }
2. 用枚举封装混合类型
创建一个枚举(比如叫DataItem)来统一管理这两种类型,关键是要实现自定义的init(from decoder:)方法,根据type字段的值来决定解析成哪种模型:
enum DataItem: Decodable { case member(Member) case imageMedium(ImageMedium) // 只定义用来判断类型的CodingKey enum CodingKeys: String, CodingKey { case type } init(from decoder: Decoder) throws { // 先解析出type字段的值 let container = try decoder.container(keyedBy: CodingKeys.self) let itemType = try container.decode(String.self, forKey: .type) // 根据type值匹配对应的模型 switch itemType { case "member": let memberModel = try Member(from: decoder) self = .member(memberModel) case "imageMedium": // 这里要和你JSON里ImageMedium对应的type值完全一致 let imageModel = try ImageMedium(from: decoder) self = .imageMedium(imageModel) default: // 遇到未知类型时,可以抛出错误或者做默认处理 throw DecodingError.dataCorruptedError( forKey: .type, in: container, debugDescription: "Unsupported item type: \(itemType)" ) } } }
3. 定义顶层响应模型
对应你给出的JSON结构,顶层是一个包含data数组的对象,所以定义一个顶层模型来承接:
struct ApiResponse: Decodable { let data: [DataItem] }
4. 执行解析并处理结果
现在就可以正常解析JSON数据了,比如从网络请求返回的Data对象解析:
// 假设jsonData是你拿到的JSON数据 let jsonData: Data = ... do { let decoder = JSONDecoder() // 如果你需要处理蛇形命名的字段(比如`owner-id`),打开下面这行 // decoder.keyDecodingStrategy = .convertFromSnakeCase let response = try decoder.decode(ApiResponse.self, from: jsonData) // 遍历数组,分别处理不同类型的对象 for item in response.data { switch item { case .member(let member): print("处理Member对象,ID:\(member.id)") // 这里写你的Member业务逻辑 case .imageMedium(let image): print("处理ImageMedium对象,ID:\(image.id)") // 这里写你的ImageMedium业务逻辑 } } } catch { print("解析出错:\(error.localizedDescription)") }
额外提示
- 一定要确保
switch里的type字符串和JSON里的完全匹配(大小写敏感),比如如果你的ImageMedium对应的type是"image",那就要改成case "image"。 - 如果需要兼容更多类型,只需要给枚举添加新的case,并在
init方法里补充对应的判断逻辑即可。
内容的提问来源于stack exchange,提问作者Grambo
相关产品推荐
相关产品推荐

