Swift中如何解析首项类型不同的JSON数组并映射为指定结构体?
解析混合类型JSON数组为自定义Codable结构体的实现方案
当然可行!Swift的Codable协议本身就支持自定义解码逻辑,刚好能处理这种数组首项是Dog、其余元素都是Turtle的混合类型场景。下面我来一步步给你讲具体实现方式:
1. 定义基础结构体和目标Result结构体
首先我们需要先定义Dog、Turtle以及最终要解析成的Result结构体,它们都遵循Codable协议:
struct Dog: Codable { let name: String let breed: String } struct Turtle: Codable { let color: String let eats: String } struct Result: Codable { let dog: Dog let turtles: [Turtle] }
2. 实现自定义解码逻辑(推荐方案)
默认的Codable解码逻辑无法直接处理这种混合类型的数组,所以我们需要给Result扩展自定义的init(from decoder: Decoder)方法。这里推荐使用UnkeyedContainer来直接遍历数组元素,这种方式更高效,不需要额外的JSON序列化转换:
extension Result { init(from decoder: Decoder) throws { // 先将整个JSON解析为一个无键容器(对应数组类型) let container = try decoder.singleValueContainer() var unkeyedContainer = try container.unkeyedContainer() // 解码第一个元素为Dog类型 guard !unkeyedContainer.isAtEnd else { throw DecodingError.dataCorruptedError(in: unkeyedContainer, debugDescription: "JSON数组为空,无法解析Dog对象") } self.dog = try unkeyedContainer.decode(Dog.self) // 遍历剩余元素,解码为Turtle数组 var turtles = [Turtle]() while !unkeyedContainer.isAtEnd { let turtle = try unkeyedContainer.decode(Turtle.self) turtles.append(turtle) } self.turtles = turtles } }
3. 解码示例
现在我们可以用示例JSON数据来测试解码逻辑:
// 你的示例JSON字符串 let jsonString = """ [ { "name": "Spot", "breed": "dalmation" }, { "color": "green", "eats": "lettuce" }, { "color": "brown", "eats": "spinach" }, { "color": "yellow", "eats": "cucumbers" } ] """ do { let decodedResult = try JSONDecoder().decode(Result.self, from: jsonString.data(using: .utf8)!) print("解析成功:") print("Dog: \(decodedResult.dog.name) (\(decodedResult.dog.breed))") print("Turtles: \(decodedResult.turtles.count)只") decodedResult.turtles.forEach { turtle in print("- 颜色:\(turtle.color),食物:\(turtle.eats)") } } catch { print("解码失败:\(error.localizedDescription)") }
运行这段代码后,你就能得到一个包含单个Dog对象和Turtle数组的Result实例,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Doug Smith
相关产品推荐
相关产品推荐

