[英]How to check and cast a type to Decodable in swift
I want to make a networking request in which I could control the response is JSON raw value [String: Any
or the Decodable
.我想发出一个网络请求,我可以在其中控制响应是 JSON 原始值
[String: Any
或Decodable
。
Here is the example:这是示例:
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()
}
then when I want JSON value I just call with T
as [String: Any]
or just use any model confirm Decodable
protocol.然后当我想要 JSON 值时,我只需将
T
作为[String: Any]
调用或仅使用任何模型确认可Decodable
协议。
The question is for this line:问题是针对这一行:
try? JSONDecoder().decode(T.self, from: data)
How to cast T
to Decodable
?如何将
T
为Decodable
?
I know to use:我知道使用:
func reqest<T: Decodable >(endpoint: EndPoint, completion: @escaping (Result<T, Error>) -> Void)
but [String: Any]
isn't Decodable
.但是
[String: Any]
不是Decodable
。
Or any better solution to achieve what I want?或者任何更好的解决方案来实现我想要的? thanks.
谢谢。
I would recommend to use overload for the reqest(endpoint:completion:)
function to achieve what you want.我建议对
reqest(endpoint:completion:)
函数使用重载来实现你想要的。
A structure that I would like for example is this:例如,我想要的结构是这样的:
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()
}
That way you can have generic response handling code in baseReqest(endpoint:completion:)
function and separate only the response parsing in the other two functions.这样你就可以在
baseReqest(endpoint:completion:)
函数中拥有通用的响应处理代码,并在其他两个函数中只分离响应解析。
Then calling reqest(endpoint:completion:)
function could be然后调用
reqest(endpoint:completion:)
函数可以是
[String: Any]
as response type:[String: Any]
作为响应类型:reqest(endpoint: endpoint) { (result: Result<[String: Any], Error>) in
// Handle result
}
[[String: Any]]
as response type:[[String: Any]]
作为响应类型:reqest(endpoint: endpoint) { (result: Result<[[String: Any]], Error>) in
// Handle result
}
Decodable
object as response type:Decodable
对象作为响应类型:struct Response: Decodable {}
reqest(endpoint: endpoint) { (result: Result<Response, Error>) in
// Handle result
}
Do it in Swift way.以 Swift 的方式来做。 Use the struct Codable (that gives you the Decodable together).
使用 struct Codable (它为您提供 Decodable )。
For example:例如:
struct testStruct: Codable {
public var testString:String!
public var testAny:Any!
init(
testString:String!,
testAny:Any!
)
{
self.testString = testString
self.testAny = testAny
}
Then you initialize it with this:然后你用这个初始化它:
var testStructToUse:[testStruct] = []
From here you can populate it with append method:从这里您可以使用 append 方法填充它:
testStructToUse.append(testStruct(testString: "any String", testAny: "any value"))
And encode with JSONencoder并使用 JSONencoder 进行编码
let jsonData = try JSONEncoder().encode(testStruct)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.