之前已经实现了:
[已解决]Swift中Alamofire的http返回401时默认属于Success而不是Failure
所以代码改为:
func getRequestRespJson(httpRequest:Alamofire.Request, mergedAllPara:Dictionary<String, AnyObject>, respJsonHandler: (Alamofire.Result<JSON, NSError>, mergedAllPara:Dictionary<String, AnyObject>) -> Void) { gLog.info(“httpRequest=\(httpRequest), mergedAllPara=\(mergedAllPara), respJsonHandler=\(respJsonHandler)”) dispatchBackground_async({ // httpRequest.responseJSON(queue: BackgroundThread, completionHandler: { response in //validate will make it to error for which status code is not within 200…299 httpRequest.validate().responseJSON(queue: BackgroundThread, completionHandler: { response in gLog.debug(“request=\(response.request), response=\(response.response), statusCode=\(response.response?.statusCode), result=\(response.result)”) /* [Debug] [com.apple.root.background-qos] [CrifanLibHttp.swift:21] request=Optional(<NSMutableURLRequest: 0x7964c340> { URL: http://qapp.chinacloudapp.cn/open/code }), response=Optional(<NSHTTPURLResponse: 0x78f82160> { URL: http://qapp.chinacloudapp.cn/open/code } { status code: 200, headers { Connection = “keep-alive”; “Content-Length” = 48; “Content-Type” = “application/json;charset=UTF-8”; Date = “Fri, 03 Jun 2016 08:42:18 GMT”; Server = “nginx/1.10.1”; } }), statusCode=Optional(200), result=SUCCESS */ let statusCode = response.response?.statusCode ?? 0 gLog.debug(“statusCode=\(statusCode)”) //2016-06-15 20:32:10.878 [Verbose] [com.apple.root.background-qos] [CrifanLibHttp.swift:76] getUrlRespJson_async(_:url:parameters:headers:extraPara:respJsonHandler:) > statusCode=200 gLog.verbose(“HTTPMethod=\(response.request?.HTTPMethod), URL=\(response.request?.URL), URLString=\(response.request?.URLString), allHTTPHeaderFields=\(response.request?.allHTTPHeaderFields))”) if let httpBodyData = response.request?.HTTPBody { let httpBodyJson = JSON(data: httpBodyData) gLog.verbose(“httpBodyJson=\(httpBodyJson)”) //httpBodyJson=unknown /* httpBodyJson={ “customer” : { “followup” : 4, “datafrom” : 2, “phone” : “”, “name” : “”, “topComeFrom” : 0, “salesId” : 10000010, “testdrive” : true, “comeFrom” : 0 }, “intentedcar” : { “color” : “0”, “spec” : “0”, “series” : “0” } } */ } switch response.result { case .Success(let value): gLog.verbose(“value=\(value), value type=\(String(value.dynamicType)))”) /* value={ code = 200; data = 13812345678; message = ok; }, value type=__NSCFDictionary) */ let valueJson = JSON(value) gLog.verbose(“valueJson=\(valueJson)”) respJsonHandler(Alamofire.Result.Success(valueJson), mergedAllPara: mergedAllPara) case .Failure(let error): /* { “message” : “Unauthorized”, “code” : 401 } */ var errorStr:String = error.localizedDescription if errorStr.isEmpty { errorStr = error.localizedFailureReason ?? “” } gLog.error(“\(httpRequest) error: \(errorStr), detail:\(error)”) //GET http://qapp.chinacloudapp.cn/token/generate error: The data couldn’t be read because it isn’t in the correct format., detail:Error Domain=NSCocoaErrorDomain Code=3840 “Invalid value around character 0.” UserInfo={NSDebugDescription=Invalid value around character 0.} //GET http://qapp.chinacloudapp.cn:8090/app/statistics/10000005/customer/analysis (401) error: 未能完成该操作。Response status code was unacceptable: 401, detail:Error Domain=com.alamofire.error Code=-6003 “Response status code was unacceptable: 401” UserInfo={StatusCode=401, NSLocalizedFailureReason=Response status code was unacceptable: 401} //let error:NSError = NSError(domain: HttpErrorDomain, code: statusCode, userInfo: [ let returnError:NSError = NSError(domain: error.domain, code: error.code, userInfo: [ “message” : errorStr, “code” : statusCode, “NSDebugDescription” : error.userInfo[“NSDebugDescription”] ?? “”, ]) updateAccessTokenIfUnauthoried(returnError) respJsonHandler(Alamofire.Result.Failure(returnError), mergedAllPara: mergedAllPara) } }) }) } |
但是现在遇到一个问题:
当服务器端返回错误,比如403,内部是给了详细的错误信息的
比如是:
{ “message” : “手机号码已经注册|403105”, “code” : 403 } |
然后内部代码可以提取出来对应的,返回的json中的message中的错误信息,提醒给用户
但是,此时,对于:
httpRequest.validate()
之后,再去:responseJSON
虽然可以进入:
case .Failure(let error):
检测到statusCode是403
但是那些json错误信息,却拿不到了。
现在希望实现的是:
在使用了httpRequest.validate().responseJSON
在服务器端返回403的错误的同时,还可以获取到对应的错误的json信息
参考:
Alamofire/Alamofire: Elegant HTTP Networking in Swift
去试试
Alamofire.request(.GET, “https://httpbin.org/get”) .validate() .responseString { response in print(“Response String: \(response.result.value)”) } .responseJSON { response in print(“Response JSON: \(response.result.value)”) } |
不过没继续试上述办法。
然后看到另外的:
Creating a Custom Response Serializer
感觉好像是需要自己重新写reponse的序列化
不过,最后的最后,找到了解决办法:
当出错的时候,response,是有data的,可以被解析为所收到的json
此处就是我们要的json了,比如:
{ “message” : “手机号码已经注册|403105”, “code” : 403 } |
然后再去写代码去解析:
完整代码是:
case .Failure(let error): /* { “message” : “Unauthorized”, “code” : 401 } */ var returnError = NSError(domain: “”, code: 0, userInfo: nil) var parseRespJsonOk = false if let respData = response.data { let respJson = JSON(data: respData) gLog.verbose(“respJson=\(respJson)”) let parsedError = parseRespError(respJson) gLog.debug(“parsedError=\(parsedError)”) if parsedError.parseOk { returnError = parsedError.parsedError parseRespJsonOk = true } } if !parseRespJsonOk { var errorStr:String = error.localizedDescription if errorStr.isEmpty { errorStr = error.localizedFailureReason ?? “” } gLog.error(“\(httpRequest) error: \(errorStr), detail:\(error)”) //GET http://qapp.chinacloudapp.cn/token/generate error: The data couldn’t be read because it isn’t in the correct format., detail:Error Domain=NSCocoaErrorDomain Code=3840 “Invalid value around character 0.” UserInfo={NSDebugDescription=Invalid value around character 0.} //GET http://qapp.chinacloudapp.cn:8090/app/statistics/10000005/customer/analysis (401) error: 未能完成该操作。Response status code was unacceptable: 401, detail:Error Domain=com.alamofire.error Code=-6003 “Response status code was unacceptable: 401” UserInfo={StatusCode=401, NSLocalizedFailureReason=Response status code was unacceptable: 401} returnError = NSError(domain: error.domain, code: error.code, userInfo: [ “message” : errorStr, “code” : statusCode, “NSDebugDescription” : error.userInfo[“NSDebugDescription”] ?? “”, ]) } updateAccessTokenIfUnauthoried(returnError) respJsonHandler(Alamofire.Result.Failure(returnError), mergedAllPara: mergedAllPara) } /* respJson={ “message” : “手机号码已经注册|403105”, “code” : 403 } */ func parseRespError(respJson:JSON) -> (parseOk:Bool, parsedError:NSError) { gLog.verbose(“respJson=\(respJson)”) var parseOk = false var parsedError = NSError(domain: “”, code: 0, userInfo: nil) guard let statusCode = respJson[“code”].int else { gLog.debug(“not found response code for respJson=\(respJson)”) return (parseOk, parsedError) } gLog.debug(“statusCode=\(statusCode)”) guard let message = respJson[“message”].string else { gLog.debug(“not found response message for respJson=\(respJson)”) return (parseOk, parsedError) } gLog.debug(“message=\(message)”) //parse message to message + subCode let messageStrArr = message.splitToStrArr(“|”) var messageStr:String = message var subCode:Int = 0 guard messageStrArr.count >= 2 else { gLog.error(“can not parse response message=\(message) to sub array”) return (parseOk, parsedError) } gLog.verbose(“messageStrArr=\(messageStrArr)”) //messageStrArr=[“手机号码已经注册”, “403105”] parseOk = true messageStr = messageStrArr[0] subCode = Int(messageStrArr[1]) ?? 0 parsedError = NSError(domain: HttpErrorDomain, code: statusCode, userInfo: [ “message” : messageStr, “code” : statusCode, “subCode” : subCode, ]) return (parseOk, parsedError) } |
即可满足此处的需求了。
[总结]
当Alamofire的httpRequest在validate之后再去responseJSON:
httpRequest.validate().responseJSON
此处得到的结果中,如果是Failure,则此时是可以通过
解析response.data而得到对应的返回的json信息的
其中就有此处我们所需要的错误信息了。
而无需额外的去写自定义的response的JSON序列化了。
转载请注明:在路上 » [已解决]如何让Alamofire在http加了validate之后再去responseJSON返回是出错的时候可以获取对应的错误信息