问题描述
我想发出一个网络请求,我可以控制响应为JSON原始值[String: Any
或Decodable
。
这里是示例:
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)