Swift Take HTTP JSON响应并使用Codable解析

时间:2018-11-27 13:18:40

标签: ios json swift alamofire codable

所以我试图通过使用Alamofire向后端服务器发出http请求来执行登录。

我有2个级别的请求方法,如下所示:

class func requestWith(url : URL, method: HTTPMethod, parameters: Parameters?, headers: HTTPHeaders, completion: @escaping (_ response: DataResponse<Any>) -> Void){

    let sessionManager = NetworkManager.sharedInstance
    sessionManager.request(url, method: method, parameters: parameters, encoding: URLEncoding.default, headers: headers)
        .validate(statusCode: 200..<300)
        .responseJSON { (response) in
            if let data = response.data {
                print("RESPONSE ALAMOFIRE: code = \(String(describing: response.response?.statusCode)), response = \(String(decoding: data, as: UTF8.self)) ")
            }
            completion(response)
    }
}

这是Alamofire请求的基本方法,我将其用于要添加的所有功能。现在遵循实际的登录方法,该方法是针对基本身份验证量身定制的。

class func loginAccount(usernameOrEmail: String?, password: String?, onSuccess success: @escaping (_ data : Data?) -> Void, onFailure failure: @escaping (_ error: Error?, _ errorData: Data?) -> Void){

    let parameters: Parameters = [
        "username" : usernameOrEmail!,
        "password" : password!,
        "grant_type" : "password"
    ]

    let authUser = "WebClient"
    let authPass = "Parola123"

    let authData = "\(authUser):\(authPass)".data(using: String.Encoding.utf8)
    guard let base64Auth = authData?.base64EncodedString(options: []) else { return }
    let headers = [
        "Authorization": "Basic \(String(describing: base64Auth))",
    "Content-Type" : "application/x-www-form-urlencoded"
    ]

    let url = Constants.urls.URL_LOGIN
    APIRequest.requestWith(url: url!, method: .post, parameters: parameters, headers: headers) { (result) in
        switch result.result {
        case .success( _ ):

            if let jsonValue = result.result.value {
                let json = JSON(jsonValue)
                do {
                    let jsonData = try json.rawData( options: [])
                    success(jsonData)

                } catch {
                    print(error.localizedDescription)
                }
            }

            break

        case .failure(let error):
            print("There was an error in logging in: \(error)")
            failure(error, result.data)
            break
        }
    }
}

最后,在LoginViewController中,点击登录按钮时调用的方法:

@IBAction func signInTapped(_ sender: Any) {
    APIRequest.loginAccount(usernameOrEmail: emailField.text, password: passwordField.text,
      onSuccess: {  (successData) in
        self.startLoadingAnimation()
        if let response = successData {
            print("Response123 is: \(response)")


            do {

                let f = try JSONDecoder().decode(tokenResponse.self, from: response)
                print("access token is: \(f.scope)")

            } catch {
                print(error.localizedDescription)
            }

            self.stopLoadingAnimation()

            if let vc = self.storyboard?.instantiateViewController(withIdentifier: "ChatLogNavi") as? UINavigationController {
                self.present(vc,animated: true, completion: nil)
            }

        } else {
            }

        }, onFailure: { (error, failureData) in
        var json = JSON()
        do {
            json = try JSON(data: failureData!)
        } catch {
        }
        let messageBody = json["message"].stringValue
        let alert = UIAlertController(title: error?.localizedDescription, message: messageBody, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default))
        self.present(alert, animated: true)
    })

    print("\n get account \n")
}

最重要的是,当我将响应从一种方法发送到另一种方法时,我不知道该如何设置响应的数据类型。最后,当我使用最后一种方法时,它什么也不会返回,而是说:“由于格式不正确,无法读取数据。”我应该修改什么?我对JSON和HTTP请求还很陌生。谢谢!

编辑:tokenResponse的声明如下:

 struct tokenResponse: Codable {
    var tokenType: String?
    var expiresIn: String?
    var refreshToken: String?
    var accessToken: String?
    var scope: String?

    enum CodingKeys: String, CodingKey {
        case tokenType = "token_type"
        case expiresIn = "expires_in"
        case refreshToken = "refresh_token"
        case accessToken = "access_token"
        case scope

    }
}

1 个答案:

答案 0 :(得分:0)

我认为您想从服务中接收json!尝试通过以下方法更改您的第一个功能:

class func requestWith(url : URL, method: HTTPMethod, parameters: Parameters?, headers: HTTPHeaders, completion: @escaping (_ response: NSDictionary) -> Void){

    let sessionManager = NetworkManager.sharedInstance
    sessionManager.request(url, method: method, parameters: parameters, encoding: URLEncoding.default, headers: headers)
        .validate(statusCode: 200..<300)
        .responseJSON { (response) in
            if let result = response.result.value {
                let jsonResponse = result as! NSDictionary
                print("Your JSON is \(jsonResponse)")
            }
            completion(jsonResponse)
    }
}

因此,通过这种方式,您可以拥有一个包含JSON的字典,以从函数中返回!之后,您可以解析它以创建对象