如何处理可能包含数组或字典的API的响应?

问题描述 投票:1回答:2

我有一个API调用,它检查UserLogin和密码,并根据用户名和密码对是否正确发送响应。

如果用户名和密码对不正确,API将返回字典,如果用户名和密码正确,则将返回字典数组。

我面临的问题是我无法将Alamofire的响应向下转换为特定的数据类型。

   func afLoginDriver(firstName: String,password:String,completion: @escaping ([Dictionary<String, Any>])->Void){
    let driverLoginURL = "URL here.."
    let parameters = ["firstName" : firstName, "Password" : password]
    AF.request(driverLoginURL, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: nil).responseJSON { response in

        switch response.result {
            case .success:
                let driverLoginResponse = response.value as? [Dictionary<String, Any>]
                completion(driverLoginResponse)
            break
        case .failure(let error):
            print(error)
        }
    }
}

如果用户名-密码对不正确,则变量driverLoginResponse会引发错误,因为它只是一个字典,而不是字典数组。

我尝试使用guard let语句,但仍然无法使它正常工作。

swift xcode alamofire
2个回答
2
投票
  1. 将响应值转换为潜在的类型,并处理每个值:
if let responseOne = response.value as? [String: Any] {
    // ...
} else if let responseTwo = response.value as? [[String: Any]] {
    // ...
}

  1. 您可以使用Codable:
struct Response: Codable {
   var valueOne: [String: Any]?
   var valueTwo: [[String: Any]]?
}


1
投票

我将为此使用Codableenum,但请考虑以下因素:

首先,以任何可能的响应实现enum

enum LoginDriverResponseValue {
    case dictionary([String: Any])
    case array([[String: Any]])
    case string(String)
    case unknown(Any)
}

然后,更改函数签名以适应该枚举:

func afLoginDriver(firstName: String, password: String, completion: @escaping (LoginDriverResponseValue)->Void) {
,,,
}

最后,打开枚举并调用相应的完成:

guard let responseValue = response.value else { return }

switch responseValue {
case let result as [String: Any]: completion(.dictionary(result))
case let result as [[String: Any]]: completion(.array(result))
case let result as String: completion(.string(result))
default: completion(.unknown(responseValue))
}

-更封装的方式:

您可以将responseValue类型检测封装到enum LoginDriverResponseValue中:

extension LoginDriverResponseValue {
    init(responseValue: Any) {
        switch responseValue {
        case let result as [String: Any]: self = .dictionary(result)
        case let result as [[String: Any]]: self = .array(result)
        case let result as String: self = .string(result)
        default: self = .unknown(responseValue)
        }
    }
}

因此,您在函数中唯一需要的是:

guard let responseValue = response.value else { return }
completion(LoginDriverResponseValue(responseValue: responseValue))
© www.soinside.com 2019 - 2024. All rights reserved.