如何解码含多类型的JSON数组?解决Decodable兼容及移除末尾Int问题
JSON混合类型数组解码问题解决:排除末尾Int或适配Decodable
为什么用AnyObject会不符合Decodable协议?
Swift的Decodable协议要求明确的类型定义,AnyObject是无类型约束的空类型,编译器无法自动推断解码规则,所以直接在struct里用AnyObject会导致无法遵守Decodable协议。
解决方案1:解码时过滤掉末尾Int,只保留字符串
通过自定义解码逻辑,先兼容混合类型的数组,再过滤出需要的字符串元素(如果确定最后一个元素是Int,也可以直接移除最后一个元素后再过滤)。
代码示例:
// 自定义枚举兼容JSON混合类型 enum JSONValue: Decodable { case string(String) case int(Int) init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() if let str = try? container.decode(String.self) { self = .string(str) } else if let int = try? container.decode(Int.self) { self = .int(int) } else { throw DecodingError.typeMismatch( JSONValue.self, DecodingError.Context( codingPath: decoder.codingPath, debugDescription: "不支持的JSON类型" ) ) } } } // 定义API响应结构体 struct MadLibResponse: Decodable { let value: [String] // 根据API实际返回补充其他字段,比如title、blanks等 enum CodingKeys: String, CodingKey { case value } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // 先解码成混合类型数组 let mixedValues = try container.decode([JSONValue].self, forKey: .value) // 方式A:过滤所有字符串元素(不管Int位置) value = mixedValues.compactMap { guard case .string(let str) = $0 else { return nil } return str } // 方式B:如果确定最后一个元素是Int,先移除再过滤 // let filteredValues = mixedValues.dropLast() // value = filteredValues.compactMap { // guard case .string(let str) = $0 else { return nil } // return str // } } }
解决方案2:保留所有混合类型元素
如果需要保留数组里的字符串和Int,直接把value定义为[JSONValue]类型,这样结构体可以正常遵守Decodable,后续使用时再区分类型处理:
struct MadLibResponse: Decodable { let value: [JSONValue] // 其他字段... } // 使用时遍历区分类型 for item in response.value { switch item { case .string(let str): print("字符串元素:\(str)") case .int(let num): print("数字元素:\(num)") } }
内容的提问来源于stack exchange,提问作者Kevin Thomas
相关产品推荐
相关产品推荐

