Swift/Alamofire 5 ResponseSerializer 通用结构解码
Swift/Alamofire 5 ResponseSerializer generic stuct decode
我正在尝试序列化一些来自 API 端点的 JSON 数据,并且因为所有端点都具有相同的结构,所以我认为这对我来说是最好的实现不需要在代码中再次重复的东西。
JSON 响应 1:
{
"code":1100,
"message":"Successfully created application",
"data":{
"key":116541
}
}
JSON 回复 2:
{
"code":1101,
"message":"Successfully retrived",
"data":{
"id":116541,
"name":"hallow"
}
}
只有数据会根据 API 端点发生变化。他们总是会以这种结构出现。
struct RawResponse<T: Decodable>: Decodable {
let code: Int
let message: String
let data: T
}
这是我不知道如何使用 Alamofire 的 DecodableResponseSerializer 解码 RawResponse 的地方。
final class CustomDecodeableResponseSerializer<T: Decodable>: ResponseSerializer {
//...decoder setup
//don't work, missing "T" because it's defined in the struct don't know where to add this
private lazy var successSerializer = DecodableResponseSerializer<RawResponse>(decoder: decoder)
//This works as it's just pure struct without generic
private lazy var errorSerializer = DecodableResponseSerializer<APIError>(decoder: decoder)
//...public func serialize stuff
}
这是行不通的,因为它要求结构中定义的“T”,而“T”是通过 DataRequest 的扩展传入的
@discardableResult
func responseCustom<T: Decodable>(queue: DispatchQueue = DispatchQueue.global(qos: .userInitiated), of t: T.Type, completionHandler: @escaping (Result<T, APIError>) -> Void) -> Self {
return response(queue: .main, responseSerializer: CustomDecodeableResponseSerializer<T>()) { response in
switch response.result {
case .success(let result):
completionHandler(result)
case .failure(let error):
completionHandler(.failure(APIError(code: -1, message: error.localizedDescription)))
}
}
}
所以可以这样调用:
User 是 JSON “数据”字段的另一个结构,将被解码为
session.request()
.validate()
.responseCustom(of: User.self){(response) in
//do stuff
}
我希望这是有道理的...我知道如果我只是传递 T 而不是制作原始响应结构,我可以在每个响应结构中重复代码和消息,它会起作用。但我力求不在每个响应结构中重复代码和消息。或者有没有更简单的方法来实现这个?
您的代码中没有它,但请确保您的 CustomDecodeableResponseSerializer
从其 serialize
方法返回 RawResponse<T>
。然后你可以确保你的成功案例的解码器是 DecodableResponseSerializer<RawResponse<T>>(decoder: decoder)
.
此外,没有理由使用 DispatchQueue.global()
。该参数仅控制调用完成处理程序的位置,实际的序列化工作始终在后台执行。
我正在尝试序列化一些来自 API 端点的 JSON 数据,并且因为所有端点都具有相同的结构,所以我认为这对我来说是最好的实现不需要在代码中再次重复的东西。
JSON 响应 1:
{
"code":1100,
"message":"Successfully created application",
"data":{
"key":116541
}
}
JSON 回复 2:
{
"code":1101,
"message":"Successfully retrived",
"data":{
"id":116541,
"name":"hallow"
}
}
只有数据会根据 API 端点发生变化。他们总是会以这种结构出现。
struct RawResponse<T: Decodable>: Decodable {
let code: Int
let message: String
let data: T
}
这是我不知道如何使用 Alamofire 的 DecodableResponseSerializer 解码 RawResponse 的地方。
final class CustomDecodeableResponseSerializer<T: Decodable>: ResponseSerializer {
//...decoder setup
//don't work, missing "T" because it's defined in the struct don't know where to add this
private lazy var successSerializer = DecodableResponseSerializer<RawResponse>(decoder: decoder)
//This works as it's just pure struct without generic
private lazy var errorSerializer = DecodableResponseSerializer<APIError>(decoder: decoder)
//...public func serialize stuff
}
这是行不通的,因为它要求结构中定义的“T”,而“T”是通过 DataRequest 的扩展传入的
@discardableResult
func responseCustom<T: Decodable>(queue: DispatchQueue = DispatchQueue.global(qos: .userInitiated), of t: T.Type, completionHandler: @escaping (Result<T, APIError>) -> Void) -> Self {
return response(queue: .main, responseSerializer: CustomDecodeableResponseSerializer<T>()) { response in
switch response.result {
case .success(let result):
completionHandler(result)
case .failure(let error):
completionHandler(.failure(APIError(code: -1, message: error.localizedDescription)))
}
}
}
所以可以这样调用: User 是 JSON “数据”字段的另一个结构,将被解码为
session.request()
.validate()
.responseCustom(of: User.self){(response) in
//do stuff
}
我希望这是有道理的...我知道如果我只是传递 T 而不是制作原始响应结构,我可以在每个响应结构中重复代码和消息,它会起作用。但我力求不在每个响应结构中重复代码和消息。或者有没有更简单的方法来实现这个?
您的代码中没有它,但请确保您的 CustomDecodeableResponseSerializer
从其 serialize
方法返回 RawResponse<T>
。然后你可以确保你的成功案例的解码器是 DecodableResponseSerializer<RawResponse<T>>(decoder: decoder)
.
此外,没有理由使用 DispatchQueue.global()
。该参数仅控制调用完成处理程序的位置,实际的序列化工作始终在后台执行。