Reputation: 3154
I'm using Liberator, and am having a hard time getting my POSTed data into a map using with keywords as the keys. Here is my resource, with a few printlines for testing:
(defresource finish_validation
:allowed-methods [:post]
:available-media-types ["application/json"]
:post! (fn [context]
(let [params (slurp (get-in context [:request :body]))
mapped_params (cheshire/parse-string params)]
(println (type params))
(println (type mapped_params))
(validation/finish mapped_params)))
:handle-created (println ))
For testing, I'm posting the data using curl:
curl -H "Content-Type: application/json" -X POST -d '{"email":"[email protected]","code":"xyz"}' http://localhost:8080/validate
cheshire converts the params into a map, but the keys are not keywords: I get {email [email protected], code xyz}
as the output, instead of the hoped-for {:email [email protected], :code xyz}
.
Should I be doing something differently? Is this even the right approach to getting the data?
Upvotes: 2
Views: 521
Reputation: 10454
You need to leverage ring's wrap-params
middleware, coupled with the wrap-keyword-params
middleware which converts the params map to a key map.
(ns your.namespace
(:require [ring.middleware.params :refer [wrap-params]]
[ring.middleware.keyword-params :refer [wrap-keyword-params]]))
(def app
(-> some-other-middleware
wrap-keyword-params
wrap-params))
Using this middleware with wrap-params
converts params to use keys. After adding this middleware, you can access your params from the request map, like so (-> ctx :request :params)
. No need to convert them per request. This will handle all requests.
Upvotes: 2
Reputation: 4235
Depending on your requirements, you can simplify the handling of your post data using various ring middleware. This will allow you to process your json data in one place and eliminate the need to have duplicate data processing in each of your handlers/resource definitions. There are a few ways of doing this. You can have the json data added as keywordized parameters in the params map or a json-params map. Have a look at ring.middleware.format and ring.middleware.json.
Upvotes: 0
Reputation: 3154
I just had to put "true" at the end of the call to the cheshire function, and the keys are returned as keywords:
(cheshire/parse-string params true)
Upvotes: 1