Alamofire 5 任何字典

Posted

技术标签:

【中文标题】Alamofire 5 任何字典【英文标题】:Alamofire 5 Any In Dictionary 【发布时间】:2020-06-08 14:27:59 【问题描述】:

我正在尝试使用 Alamofire 5 进行发布请求。我必须使用 Dictionary<String, Any> 作为参数。因为我正在为 Alamofire 编写一个包装器。但似乎我无法使用字典中的任何对象,因为 Alamofire 给了我一个编译器错误:

Value of protocol type 'Any' cannot conform to 'Encodable'; only struct/enum/class types can conform to protocols

我尝试过的:

    let encodedParameters = Dictionary<String, Any>

    AF.request(url, method: .get, parameters: encodedParameters, headers: headers)

在我的字典中,一些值将是字符串,而另一些值将是整数。所以我不能使用常量类型。我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

要使用新的request,您可以为请求参数创建自己的结构:

// you might have...
struct FooRequestParameters : Codable 
    let paramName1: Int
    let paramName2: String


// for another type of request, you might have different parameters...
struct BarRequestParameters: Codable 
    let somethingElse: Bool

您可以传递FooRequestParameters(paramName1: 1, paramName1: "hello") 而不是您的字典。这与传递字典相同:

[
    "paramName1": 1,
    "paramName2": "hello"
]

此 API 更改背后的基本原理可能具有更高的安全性。使用[String: Any],您可以很容易地,例如,将String 值赋予应该是Int 的参数,或者错误地输入参数的名称,或者在没有意识到的情况下遗漏了一些参数......等等。

【讨论】:

感谢您的回答。我只是想弄清楚,管理这些结构的最佳实践是什么?我应该在一个文件中定义所有这些吗? @TolgayToklar 我认为这取决于您的偏好和您的编码风格。对我来说,如果我只在一个地方发送请求,我想将它们放在与我发送请求相同的文件中。否则我会把它单独放在一个文件中。 感谢您的回复,在您发表评论之前我刚刚找到解决方案,这就是我删除评论的原因【参考方案2】:

这是因为您使用的是较新的方法,它需要 parameters 参数为 Encodable。使用较旧的 Alamofire 方法,您会没事的:

AF.request(url, method: .get, parameters: encodedParameters, encoding: JSONEncoding.default, headers: headers)

更新:如果您想使用最新的 Alamofire 5 语法,请创建一个结构并确认它是可编码的。然后用值创建一个相同结构的对象并传递它。

【讨论】:

是的,我知道,但我正在寻找 alamofire 5 way 对于 alamofire 5,您必须使结构确认它为 Encodable 并传递它的对象。 所以我必须为每个其他 api 请求创建许多结构? 是的,除非您传递相同的参数集。【参考方案3】:

如果你想传递[String: Any]的参数,你不需要创建structs并采用encodable协议。可以这样实现:

import Foundation
import Alamofire

enum ServiceRouter 
    case fetchCountries
    case fetchUserRepositories
    
    var baseURL: String 
        switch self 
        case .fetchCountries:
            return "https://restcountries.eu/rest/v2"
        
    
    
    var path: String 
        switch self 
        case .fetchCountries:
            return "/all"
        
    
    
    var method: HTTPMethod 
        switch self 
        case .fetchCountries:
            return .get
        default:
            return .post
        
    
    
    var parameters: Parameters? 
        switch self 
        case .fetchUserRepositories:
            return ["per_page": 100]
            
        default:
            return [:]
        
    


// MARK: - URLRequestConvertible
extension ServiceRouter: URLRequestConvertible 
    func asURLRequest() throws -> URLRequest 
        let url = try baseURL.asURL().appendingPathComponent(path)
        var request = URLRequest(url: url)
        request.method = method
        if method == .get 
            request = try URLEncoding.default.encode(request, with: parameters)
         else if method == .post 
            request = try JSONEncoding.default.encode(request, with: parameters)
        
        return request
    

您可以将此请求用作

AF.request(ServiceRouter.fetchCountries).responseData  (response) in 

【讨论】:

以上是关于Alamofire 5 任何字典的主要内容,如果未能解决你的问题,请参考以下文章

Alamofire 多参数字典

Alamofire 5.0.0-rc.3 RequestInterceptor Adapt 方法没有被调用 Alamofire 虽然在响应中有任何错误时会调用重试

Alamofire 的格式化字典

Alamofire:创建字典数组

Alamofire 不允许直接发送对象

Alamofire 无法将 NSCFString 类型转换为字典