Swift 4中如何解码[String: AnyObject]类型字典?
解决Swift 4中[String: AnyObject]无法解码的问题
这个问题在处理多类型混合的API响应时太常见了——AnyObject本身并没有遵循Decodable协议,直接用[String: AnyObject]作为解码目标必然会触发你遇到的崩溃。既然你的值可能是Int或Double(甚至可能有其他类型),我们可以通过自定义一个可解码的通用值容器来完美解决这个问题。
步骤1:定义支持多类型的枚举
先创建一个枚举JSONValue,它涵盖你需要处理的所有值类型(比如Int、Double、String,后续可以按需扩展),然后让它遵循Decodable协议并实现自定义解码逻辑:
enum JSONValue: Decodable { case int(Int) case double(Double) case string(String) // 后续如果需要支持Bool、数组等类型,直接添加对应的case即可 init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() // 按优先级尝试解码不同类型(注意Int要放在Double前面,否则Int值会被解码成Double) if let intValue = try? container.decode(Int.self) { self = .int(intValue) } else if let doubleValue = try? container.decode(Double.self) { self = .double(doubleValue) } else if let stringValue = try? container.decode(String.self) { self = .string(stringValue) } else { throw DecodingError.dataCorruptedError(in: container, debugDescription: "无法解码为支持的数值/字符串类型") } } // 便捷属性,快速取出对应类型的值 var intValue: Int? { guard case .int(let value) = self else { return nil } return value } var doubleValue: Double? { switch self { case .int(let value): return Double(value) case .double(let value): return value default: return nil } } var stringValue: String? { guard case .string(let value) = self else { return nil } return value } }
步骤2:替换原有的[String: AnyObject]类型
把你代码中需要解码的[String: AnyObject]替换成[String: JSONValue]。比如如果是某个响应模型中的属性:
struct APIResponse: Decodable { let result: [String: JSONValue] // 其他响应属性... }
步骤3:结合Alamofire 5使用
在你的performRequest方法中,直接将泛型T指定为包含[String: JSONValue]的模型(或者直接用[String: JSONValue]作为T):
private static func performRequest<T: Decodable>(path: String, completion: @escaping (Result<T, Error>) -> Void) { AF.request(path) .responseDecodable(of: T.self) { response in switch response.result { case .success(let model): completion(.success(model)) case .failure(let error): completion(.failure(error)) } } } // 使用示例 performRequest<[String: JSONValue]>(path: "your-target-api-path") { result in switch result { case .success(let dataDict): // 取出值的示例 if let userAge = dataDict["age"]?.intValue { print("用户年龄:\(userAge)") } if let userHeight = dataDict["height"]?.doubleValue { print("用户身高:\(userHeight)") } case .failure(let error): print("请求解码失败:\(error.localizedDescription)") } }
额外提示
- 如果你的API返回值还有其他类型(比如Bool、嵌套数组),可以在
JSONValue枚举中添加对应的case,并在init(from:)方法中补充解码逻辑。 - 如果你需要将
JSONValue重新编码为数据,也可以让它遵循Encodable协议,实现对应的encode(to:)方法。
内容的提问来源于stack exchange,提问作者Bogdan Razvan
相关产品推荐
相关产品推荐

