使用泛型/可编码 w/ API 响应 204 NO CONTENT

Posted

技术标签:

【中文标题】使用泛型/可编码 w/ API 响应 204 NO CONTENT【英文标题】:Using Generics / Codable w/ API response 204 NO CONTENT 【发布时间】:2019-01-06 10:46:46 【问题描述】:

我正在使用泛型和可编码 URLSession

当我收到来自 API 的响应时,我会检查状态是否在 200 - 299 范围内并像这样解码数据

        guard let data = data, let value = try? JSONDecoder().decode(T.self, from: data) else 
            return completion(.error("Could not decode JSON response"))
        
        completion(.success(value)) 

然后将其传递给完成处理程序,一切正常。

我有一个新的端点我也必须发布,但是这个端点返回一个没有内容正文的 204。

因此,我无法解码响应,就像我无法传入类型一样?

我的完成处理程序期望

enum Either<T> 
    case success(T)
    case error(String?)

并像这样打开我的响应状态代码

   case 204:
        let value = String(stringLiteral: "no content")
        return completion(.success(value))

产生一个错误

'Either>'中的成员'success'产生'Either'类型的结果, 但上下文期望'要么>'

我的 APIClient 是

protocol APIClientProtocol: class 
    var task: URLSessionDataTask  get set 
    var session: SessionProtocol  get 
    func call<T: Codable>(with request: URLRequest, completion: @escaping (Either<T>) -> Void) -> Void
    func requestRefreshToken<T: Codable>(forRequest failedRequest: URLRequest, completion: @escaping (Either<T>) -> Void) -> Void


extension APIClientProtocol 
    func call<T: Codable>(with request: URLRequest, completion: @escaping (Either<T>) -> Void) -> Void 
        task = session.dataTask(with: request, completionHandler:  [weak self] data, response, error in
            guard error == nil else 
                return completion(.error("An unknown error occured with the remote service"))
            
            guard let response = response as? HTTPURLResponse else 
                return completion(.error("Invalid HTTPURLResponse recieved"))
            

            switch response.statusCode 
            case 100...299:
                guard let data = data else  return completion(.error("No data in response")) 
                guard let value = try? JSONDecoder().decode(T.self, from: data) else  return completion(.error("Could not decode the JSON response")) 
                completion(.success(value))
            case 300...399: return completion(.error(HTTPResponseStatus.redirection.rawValue))
            case 400: return completion(.error(HTTPResponseStatus.clientError.rawValue))
            case 401: self?.requestRefreshToken(forRequest: request, completion: completion)
            case 402...499: return completion(.error(HTTPResponseStatus.clientError.rawValue))
            case 500...599: return completion(.error(HTTPResponseStatus.serverError.rawValue))
            default:
                return completion(.error("Request failed with a status code of \(response.statusCode)"))
            
        )
        task.resume()
    

【问题讨论】:

返回.error(value) 是一种选择吗?或者添加第三种情况。顺便问一下,为什么错误情况下的字符串是可选的? nil 值没有意义。我什至会在解码 JSON 并返回它时 catch 错误 (case error(DecodingError)) 你能发布你的网络客户端吗?但是请使用 URLSession 【参考方案1】:

使您的 Either 枚举成功类型可选

enum Either<T> 
    case success(T?)
    case error(String)

204 响应状态创建一个案例,传递 nil

    case 204:
        completion(.success(nil))

然后您可以使用typealias 并创建类似的通用内容

typealias NoContentResponse = Either<Bool>

然后您应该能够打开NoContentResponse

【讨论】:

以上是关于使用泛型/可编码 w/ API 响应 204 NO CONTENT的主要内容,如果未能解决你的问题,请参考以下文章

如何在“可编码”响应中使用字典?

Android studio gradle 与 firebase 同步错误:响应 204:No Content 没有内容

带有可编码数组的 swift 5 抽象网络响应

使用 Codable 或 ObjectMapper 映射通用 API 响应

Lumen 确实发送 204 响应

如何为以下 API 数据创建可编码结构