Swift如何正确解码包含不同数据类型的JSON数组?
你遇到的两个报错根源一致:Swift 原生Codable协议不支持Any、AnyClass这类动态类型的自动编解码,JSONDecoder没有内置解析Any类型的方法,也无法为包含动态类型的结构体自动合成编解码实现。你第二次尝试的代码还有一个问题:外层JSON是对象结构,不能直接获取decoder.unkeyedContainer,需要先拿到外层的键控容器,再取出arr字段对应的数组容器。
方案1:用类型安全的枚举封装混合元素(推荐)
Swift 推荐用枚举处理固定类型的混合值,既符合类型安全规范,也不需要手动处理整个数组的遍历逻辑:
// 定义可存储Int或String的枚举,遵守Codable协议 enum IntOrString: Codable { case int(Int) case string(String) init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() if let intVal = try? container.decode(Int.self) { self = .int(intVal) return } if let strVal = try? container.decode(String.self) { self = .string(strVal) return } throw DecodingError.dataCorruptedError(in: container, debugDescription: "元素既不是Int也不是String") } } // 改造后的MOCK结构体 struct MOCK: Codable { var array: [IntOrString] enum CodingKeys: String, CodingKey { case array = "arr" } }
你原有foo函数的解码逻辑不需要修改即可直接运行,取值时只需判断枚举的对应case即可拿到实际值。
方案2:手动解析为[Any]数组
如果你确实需要保留[Any]类型的结果,可以手动遍历数组逐个解析元素:
struct MOCK: Decodable { let array: [Any] enum CodingKeys: String, CodingKey { case array = "arr" } init(from decoder: Decoder) throws { // 先拿到外层JSON对象对应的键控容器 let container = try decoder.container(keyedBy: CodingKeys.self) // 再取出arr字段对应的数组无键容器 var unkeyedContainer = try container.nestedUnkeyedContainer(forKey: .array) var tempArray = [Any]() // 遍历数组所有元素逐个解析 while !unkeyedContainer.isAtEnd { if let intVal = try? unkeyedContainer.decode(Int.self) { tempArray.append(intVal) } else if let strVal = try? unkeyedContainer.decode(String.self) { tempArray.append(strVal) } // 若有其他支持的类型可在此处继续扩展判断逻辑 } array = tempArray } }
内容的提问来源于stack exchange,提问作者Sirop4ik
相关产品推荐
相关产品推荐

