如何快速检查并将类型转换为可解码

问题描述

我想发出一个网络请求,我可以控制响应为JSON原始值[String: AnyDecodable

这里是示例:

func reqest<T>(endpoint: EndPoint,completion: @escaping (Result<T,Error>) -> Void) {
   session.dataTask(with: request) { (data,response,error) in

       if T.self is Decodable.Type {
           try? JSONDecoder().decode(T.self,from: data)
       } else {
           try? JSONSerialization.jsonObject(with: data,options: .mutableLeaves)
       }
   }.resume()
}

然后,当我想要JSON值时,我只用T来调用[String: Any]或只使用任何模型确认Decodable协议。

问题在于这一行:

try? JSONDecoder().decode(T.self,from: data)

如何将T投射到Decodable

我知道要使用:

func reqest<T: Decodable >(endpoint: EndPoint,Error>) -> Void)

但是[String: Any]不是Decodable

或者实现我想要的更好的解决方案?谢谢。

解决方法

我建议对reqest(endpoint:completion:)函数使用重载来实现所需的功能。

例如,我想要一个结构:

enum ResponseError: Error {
    case noData
    case typeMismatch
}

func reqest<T>(endpoint: EndPoint,completion: @escaping (Result<T,Error>) -> Void) {
    baseReqest(endpoint: endpoint) { result in
        switch result {
        case .success(let data):
            do {
                guard let json = try JSONSerialization.jsonObject(with: data) as? T else {
                    completion(.failure(ResponseError.typeMismatch))
                    return
                }
                completion(.success(json))
            } catch {
                completion(.failure(error))
            }
        case .failure(let error):
            completion(.failure(error))
        }
    }
}

func reqest<T: Decodable>(endpoint: EndPoint,Error>) -> Void) {
    baseReqest(endpoint: endpoint) { result in
        switch result {
        case .success(let data):
            do {
                let response = try JSONDecoder().decode(T.self,from: data)
                completion(.success(response))
            } catch {
                completion(.failure(error))
            }
        case .failure(let error):
            completion(.failure(error))
        }
    }
}

private func baseReqest(endpoint: EndPoint,completion: @escaping (Result<Data,Error>) -> Void) {
    session.dataTask(with: request) { (data,response,error) in
        if let error = error {
            completion(.failure(error))
            return
        }
        guard let data = data else {
            completion(.failure(ResponseError.noData))
            return
        }
        completion(.success(data))
    }.resume()
}

这样,您可以在baseReqest(endpoint:completion:)函数中使用通用的响应处理代码,而在其他两个函数中仅将响应解析分开。

然后调用reqest(endpoint:completion:)函数可能是

  • 使用[String: Any]作为响应类型:
reqest(endpoint: endpoint) { (result: Result<[String: Any],Error>) in
    // Handle result
}
  • 使用[[String: Any]]作为响应类型:
reqest(endpoint: endpoint) { (result: Result<[[String: Any]],Error>) in
    // Handle result
}
  • ,还使用Decodable对象作为响应类型:
struct Response: Decodable {}

reqest(endpoint: endpoint) { (result: Result<Response,Error>) in
    // Handle result
}
,

以Swift方式执行。使用结构Codable(可同时提供Decodable)。

例如:

 struct testStruct: Codable {
   public var testString:String!
   public var testAny:Any!
   init(
          testString:String!,testAny:Any!
       )
   {
       self.testString = testString
       self.testAny = testAny
   }

然后使用以下代码对其进行初始化:

var testStructToUse:[testStruct] = []

您可以从此处使用append方法填充它:

testStructToUse.append(testStruct(testString: "any String",testAny: "any value"))

并使用JSONencoder进行编码

let jsonData = try JSONEncoder().encode(testStruct)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...