Skip to content
This repository has been archived by the owner on Mar 8, 2024. It is now read-only.

Set a default, global encoder/decoder #15

Open
kevinrenskers opened this issue Apr 28, 2020 · 6 comments
Open

Set a default, global encoder/decoder #15

kevinrenskers opened this issue Apr 28, 2020 · 6 comments

Comments

@kevinrenskers
Copy link

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 a HttpData.Json body. Would it be possible to set a global default instead?

@kevinrenskers
Copy link
Author

kevinrenskers commented Apr 28, 2020

The same would be very useful to set a global dateEncodingStrategy.

@borchero
Copy link
Owner

Makes sense, I'll think about how to integrate this properly.

@kevinrenskers
Copy link
Author

kevinrenskers commented Apr 29, 2020

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.

@borchero
Copy link
Owner

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 ...

@kevinrenskers
Copy link
Author

kevinrenskers commented Apr 29, 2020

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.

@aplr
Copy link
Contributor

aplr commented Mar 27, 2021

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 JsonRequests, 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 JsonRequests and HttpBodys 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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants