[英]Generic Decodable without decoding
I am using a generic approach to decode JSONresponse generated by AlamoFire. 我正在使用一种通用方法来解码AlamoFire生成的JSONresponse。 My function is the following :
我的功能如下:
private func fetch<T: Swift.Decodable>(URLRequest: URLRequestConvertible) -> SignalProducer<T, NetworkError> {
return Network.request(URLRequest)
.attemptMap { JSON in
do {
let jsondata = try JSONSerialization.data(withJSONObject: JSON as! [String:Any], options: .prettyPrinted)
return .success(try JSONDecoder().decode(T.self, from: jsondata))
} catch let error {
Logger.shared.error("Error while decoding a JSON", error: error as NSError, userInfo: ["json" : JSON, "urlRequest" : URLRequest.urlRequest!.debugDescription])
return .failure(.incorrectDataReturned)
}
}
}
For each of my request, I have created a struct that follows the Decodable protocol. 对于我的每个请求,我创建了一个遵循Decodable协议的结构。
For one request, I do not want to decode the JSON because its structure is complex and because I just need to send it back in another request, I just want to save the response in a struct for instance like this one : 对于一个请求,我不想解码JSON,因为它的结构很复杂,并且因为我只需要在另一个请求中将其发送回去,所以我只想将响应保存在这样的结构中:
struct GenericResponse: Swift.Decodable {
let data: Data
}
where data is the response. 数据是响应。 So, I just want to take the response and put it in a struct without further decoding.
因此,我只想获取响应并将其放入结构中,而无需进一步解码。
Is it possible without braking the genericity of my function ? 是否可以不破坏我的功能的通用性? Is their a way to build a decoder that do not decode if T.self is of a certain type ?
如果T.self是某种类型,他们是否有办法构建不解码的解码器?
If you want to avoid the decoding of a specific response, you can overload the fetch
function to handle that case. 如果要避免解码特定的响应,则可以重载
fetch
函数来处理这种情况。
See the following example where the second fetch method
is overloaded to save the response data inside a struct instead of going through the decoding process. 请参见以下示例,其中第二个访存
method
被重载以将响应数据保存在结构中,而不是通过解码过程。
typealias JSON = [String: Any]
protocol RawResponse {
init(data: Data)
}
// 1
func fetch<T: Decodable>(json: JSON) -> T? {
guard let jsonData = try? JSONSerialization.data(withJSONObject: json, options: []),
let response = try? JSONDecoder().decode(T.self, from: jsonData) else {
return nil
}
return response
}
// 2
func fetch<T: RawResponse>(json: JSON) -> T? {
guard let jsonData = try? JSONSerialization.data(withJSONObject: json, options: []) else {
return nil
}
return T(data: jsonData)
}
With this overload, if a response struct
conforms to RawResponse
instead of Decodable
(as we don't need to actually decode the data), the fetch
overload is triggered. 有了这种重载,如果响应
struct
符合RawResponse
而不是Decodable
(因为我们不需要实际解码数据),则会触发fetch
重载。
struct UserResponse: Decodable {
var username: String
}
let userJson: JSON = [
"username": "someUser"
]
let user: UserResponse? = fetch(json: userJson) // call fetch #1
user?.username // someUser
struct GenericResponse: RawResponse {
var data: Data
}
let notParsable: JSON = [
"someKey": "someValue"
]
let rawData: GenericResponse? = fetch(json: notParsable) // call fetch #2
rawData?.data // 23 bytes
I dont really understand what you are trying to achieve. 我不太了解您要达到的目标。 But I faced this situation where I needed to decode using Generics.
但是我遇到这种情况,需要使用泛型进行解码。
That is why I wrote a DecoderHelper class that enables me to decode Generic Array or Generic Object (depends on your JSON response). 这就是为什么我写了一个DecoderHelper类,使我能够解码通用数组或通用对象(取决于您的JSON响应)的原因。
Maybe it can inspire you, and you will find how to optimize it or understand your situation/issue. 也许它可以激发您的灵感,您将找到如何对其进行优化或了解您的处境/问题。
final class DecoderHelper {
static func decodeGenericObject<T: Decodable>(data: Data, completion : (Result<T, ErrorResult>) -> Void) {
do {
let decoder = JSONDecoder()
let decodedData = try decoder.decode(T.self, from: data)
completion(Result.success(decodedData))
} catch {
completion(Result.failure(.decoder(error: error)))
}
}
static func decodeGenericArray<T: Decodable>(data: Data, completion : (Result<[T], ErrorResult>) -> Void) {
do {
let decoder = JSONDecoder()
let decodedData = try decoder.decode([T].self, from: data)
completion(Result.success(decodedData))
} catch {
completion(Result.failure(.decoder(error: error)))
}
}
}
PS: Why do you want to send it to an other request because "the JSON structure is too complex" ? PS:为什么由于“ JSON结构太复杂”而要发送给另一个请求?
It's pretty simple to parse a JSON file now with the Codable protocol. 现在使用Codable协议解析JSON文件非常简单。
Give it a try and train yourself, now that I'm comfortable with it, I love parsing JSON. 尝试一下并训练一下自己,现在,我已经习惯了,我喜欢解析JSON。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.