ring-clojure / ring-json

Ring middleware for handling JSON
313 stars 47 forks source link

Allow array json bodies to become json-params #56

Closed mindbat closed 6 years ago

mindbat commented 6 years ago

Currently, when using the wrap-json-params middleware, if the incoming json body for a request is valid json, but happens to be an array, the body will be consumed by the middleware, but nothing will be added to the :json-params.

This PR changes the behavior of the assoc-json-params fn to allow array json bodies to be added to the :json-params in the request. It does not add array bodies to the request :params, though.

We were recently bitten by this in a service where one of our endpoints needs to take in an array json body, and our handlers all look in :json-params for the data they need to fulfill the request.

weavejester commented 6 years ago

Any keyword that ends in -params in a Ring request is a map by convention, which is why nothing is added to the :json-params key.

It's generally recommended that you use the wrap-json-body middleware instead.

mindbat commented 6 years ago

Understood. Normally I'd agree with you, but our codebase (many dozens of handlers) assumes parsed json ends up in the :json-params part of the request map, not the body.

Rather than change our entire codebase because of the needs of one endpoint, or add a second (possibly conflicting) middleware on top of wrap-json-params, I thought it easiest to make this one small change.

weavejester commented 6 years ago

I'd rather not make a change that breaks a convention in Ring, especially if there's already middleware that does that job.

mindbat commented 6 years ago

Again, totally understand. Maybe I was't being clear, but there isn't any middleware that will do what we need it to do. Namely, put a perfectly parseable json body into the json-params of the request.

We ended up writing our own version of this middleware to get the job done. Just thought someone else might benefit from the change.

weavejester commented 6 years ago

The wrap-json-body middleware will put the parsed JSON body in the request map under the :body key. The only thing that Ring-JSON doesn't currently do is to put non-map data into the :json-params key, because that would violate one of Ring's conventions. Changing the type of an existing key may break existing libraries, and I don't think that's worth it just to avoid a straightforward refactor.