簡體   English   中英

如何快速檢查類型並將其轉換為可解碼

[英]How to check and cast a type to Decodable in swift

我想發出一個網絡請求,我可以在其中控制響應是 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)

如何將TDecodable

我知道使用:

func reqest<T: Decodable >(endpoint: EndPoint, completion: @escaping (Result<T, 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, completion: @escaping (Result<T, 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 的方式來做。 使用 struct 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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM