You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:54:39