如何在Alamofire中传递混合类型参数且不使用即将废弃的API?
解决Alamofire混合类型参数请求的Encoder报错问题
问题背景
在Alamofire中发送包含混合类型的参数请求时,使用新的encoder API会触发如下错误:
Type 'Any' cannot conform to 'Encodable'
原报错代码:
let params = [ "page": 1, "userdIds": [1,2,3], "domain": "github.com" ] as [String : Any] // Error: Type 'Any' cannot conform to 'Encodable' return try! AF.request(url, parameters: params, encoder: URLEncodedFormParameterEncoder.default)
使用旧的encoding API可临时解决问题,但该API已被标记为废弃:
return try! AF.request(url, parameters: params, encoding: URLEncoding.default)
替代解决方案
方案1:定义符合Encodable的参数结构体(官方推荐)
通过强类型结构体定义参数,天然满足Encodable协议要求,同时获得类型安全校验:
struct RequestParameters: Encodable { let page: Int let userdIds: [Int] let domain: String } let params = RequestParameters(page: 1, userdIds: [1,2,3], domain: "github.com") return try! AF.request(url, parameters: params, encoder: URLEncodedFormParameterEncoder.default)
方案2:使用Parameters类型配合自定义编码器
若不想定义结构体,可使用Alamofire内置的Parameters类型([String: Any]别名),并配置自定义编码器兼容任意类型:
let params: Parameters = [ "page": 1, "userdIds": [1,2,3], "domain": "github.com" ] // 配置编码器适配混合类型参数 let encoder = URLEncodedFormParameterEncoder( destination: .methodDependent, arrayEncoding: .noBrackets, boolEncoding: .numeric ) return try! AF.request(url, parameters: params, encoder: encoder)
注:该方式丢失类型安全,仅适合临时过渡场景。
方案3:自定义Encodable包装器处理Any类型
通过自定义包装结构体实现任意类型的Encodable兼容,兼顾灵活性与协议要求:
struct AnyEncodable: Encodable { let value: Any func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() switch value { case let number as NSNumber: if number.isBool { try container.encode(number.boolValue) } else { try container.encode(number) } case let string as String: try container.encode(string) case let array as [Any]: try container.encode(array.map(AnyEncodable.init)) case let dict as [String: Any]: try container.encode(dict.mapValues(AnyEncodable.init)) default: throw EncodingError.invalidValue( value, EncodingError.Context( codingPath: encoder.codingPath, debugDescription: "Unsupported type" ) ) } } } extension NSNumber { var isBool: Bool { String(cString: objCType) == "c" } } // 使用示例 let params: [String: AnyEncodable] = [ "page": AnyEncodable(1), "userdIds": AnyEncodable([1,2,3]), "domain": AnyEncodable("github.com") ] return try! AF.request(url, parameters: params, encoder: URLEncodedFormParameterEncoder.default)
内容的提问来源于stack exchange,提问作者Farid
相关产品推荐
相关产品推荐

