0

我正在尝试JSONDecoder使用 Alamofire 解码来自我的服务器的 json 响应。当我用 a 解码响应时guard,它可以正常工作。这种方法的副作用是,当解码实际失败时,我不知道问题出在哪里。

guard let result: TResponseData = try? decoder.decode(TResponseData.self, from: response.data!) else {
    self.logger.error("Unable to decode the response data into a model representation.")
    return
}

所以相反,我想使用 ado { } catch { }但我无法弄清楚我应该如何在 AlamofireresponseJSON回调中使用它。

这是我目前得到的:

Alamofire.request(completeUrl, method: .post, parameters: parameters, encoding: encoding, headers: headers)
.validate()
 .responseJSON { (response) -> Void in
    self.logger.info("POST Response: \(String(describing:response.response?.statusCode))")
    switch response.result {
    case .success(_):
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .custom(Date.toTMDBDate)

        do {
            let _ = try decoder.decode(TResponseData.self, from: response.data!)
        } catch DecodingError.dataCorrupted(let error) {
            self.logger.error(error.underlyingError)
            return
        }

        completion(result)
        return
    case .failure(let error):
      //....
    }

然而,这段代码给我的是一个编译器错误.responseJSON { (response) -> Void in

从“(_) -> Void”类型的抛出函数到非抛出函数类型“(DataResponse) -> Void”的无效转换。

保护代码工作正常,如果我将其更改try为 atry?或强制展开,它会编译 - 我只是无法让我的 catch 处理实际错误。

如果我更改catch块以使其不包含任何模式,则代码将编译。

catch {
    return
}

这并没有给我任何我给我的东西guard。我真的很想捕获操作遇到的错误decode。我使用了错误的模式吗?为什么使用该DecodingError.dataCorrupted模式似乎会改变回调签名?

4

1 回答 1

1

JSONDecoder可以抛出除DecodingError.dataCorrupted;以外的错误 你需要能够处理任意 Error被抛出的情况。因此,如果您想处理该错误,您将需要一个无条件catch {}块。

你也可以:

  • 当您使用responseData.responseJSONJSONDecoder
  • 如果需要,使用unwrap()AlamofireResult类型上的方法将网络错误与解码错误合并。

这就是它的样子:

Alamofire
    .request(
        completeUrl, method: .post, parameters: parameters,
        encoding: encoding, headers: headers
    )
    .validate()
    .responseData { response in

        self.logger.info(
            "POST Response: \(response.response?.statusCode as Any)"
        )

        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .custom(Date.toTMDBDate)

        do {
            let result = try decoder.decode(
                TResponseData.self, from: response.result.unwrap()
            )
            completion(result)
        } catch {
            self.logger.error(error)
        }
    } 

尽管这里要注意的一件事是,completion如果请求失败,您就不会打电话;我会亲自更改您所做的更改,并通过completion获取Result<TResponseData>参数来传播错误。

在这种情况下,您可以使用Result'flatMap(_:)方法而不是unwrap()和一个catch {}块:

func doRequest(_ completion: @escaping (Result<TResponseData>) -> Void) {

    let completeURL = // ...
    let parameters =  // ...
    let encoding =    // ...
    let headers =     // ...

    Alamofire
        .request(
            completeURL, method: .post, parameters: parameters,
            encoding: encoding, headers: headers
        )
        .validate()
        .responseData { response in

            self.logger.info(
                "POST Response: \(response.response?.statusCode as Any)"
            )

            let decoder = JSONDecoder()
            decoder.dateDecodingStrategy = .custom(Date.toTMDBDate)

            // if response.result is successful data, try to decode.
            // if decoding fails, result is that error.
            // if response.result is failure, result is that error.
            let result = response.result.flatMap {
                try decoder.decode(TResponseData.self, from: $0)
            }
            .ifFailure {
                self.logger.error($0)
            }

            completion(result)
        }
}
于 2017-10-25T12:56:49.853 回答