Open kevinrenskers opened 4 years ago
The same would be very useful to set a global dateEncodingStrategy
.
Makes sense, I'll think about how to integrate this properly.
While I can use my own JSONEncoder on every instance of HttpData.Json
(not ideal but possible), it seems impossible to use my own JSONDecoder on the response. So it's currently not possible to change dateEncodingStrategy
for the decoding of JSON, which means I have to store dates as strings now, and then manually format them to Date objects.
Do you have any idea how to solve this problem elegantly? I haven't come up with a way that aligns with the design of the library as a whole, but it should definitely be part of the library ...
I think it's tricky. I'd probably just go with a singleton configuration object where you can set your own encoder and decoder. Squid.config.decoder = ...
or something like that. Adding it decoder to HttpService
would be nicer, but not sure how easy it is to get a hold of that when making the request?
But you'd still want to be able to override it per request as well I imagine. So maybe make it possible to set your own decoder on JsonRequest
. You can already set your own encoder on HttpData.Json
so that should be good to keep as-is I guess.
Picking up on this old topic, I thought about this too, but it does not really make sense to add a global JSON encoder/decoder to the HttpService as it should not behave differently for only json requests. So maybe it makes sense to create a JsonHttpService
which, when facing JsonRequest
s, falls back to the globally defined decoder when decoding. However, the suggestion of a global encoder/decoder in the config like Squid.config.decoder = ...
is also tempting.
For the while being, what I'm doing right now is defining a global encoder/decoder by myself, overwriting the default ones on my custom JsonRequest
s and HttpBody
s like so:
extension MyApi {
static var encoder: JSONEncoder = {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .useDefaultKeys
return encoder
}()
static var decoder: JSONDecoder = {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .useDefaultKeys
decoder.dateDecodingStrategy = .custom({ decoder -> Date in
let container = try decoder.singleValueContainer()
let dateString = try container.decode(String.self)
guard let date = ISO8601DateFormatter.default.date(from: dateString) else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Cannot decode date string \(dateString)")
}
return date
})
return decoder
}()
}
Then, in the request, I do the following:
struct CreateUserRequest: JsonRequest {
typealias Result = UserDto
let user: UserData
var routes: HttpRoute {
["user"]
}
var method: HttpMethod = .post
var body: HttpBody {
HttpData.Json(user, encoder: MyApi.encoder)
}
func decode(_ data: Data) throws -> Result {
try MyApi.decoder.decode(Result.self, from: data)
}
}
Hope this helps.
The API that I am working with does not use snake_case, but rather camelCase. That means that I now have to supply my own
JSONEncoder
every time I use aHttpData.Json
body. Would it be possible to set a global default instead?