How to get JSON post data in Noir

1k views Asked by At

A while back, Chris Granger posted this middleware to get JSON hashes to appear in the defpage params under an umbrella "backbone" element.

(defn backbone [handler]
  (fn [req]
    (let [neue (if (= "application/json" (get-in req [:headers "content-type"]))
       (update-in req [:params] assoc :backbone (json/parse-string (slurp (:body req)) true))
       req)]
    (handler neue))))

How could I modify this code to have the JSON elements appear as top-level params in defpage; i.e. get rid of the :backbone umbrella?

3

There are 3 answers

1
Jeremy On BEST ANSWER

There are two things you can do. One option is to replace the value of :params with the map returned after parsing the JSON. In order to do that, just associate the new map to the :params key.

(assoc req [:params] (json/parse-string (slurp (:body req)) true))

The other option (as suggested by @dAni) is to merge the values of the parsed JSON into so that existing values in the :params map are not overridden. The reason why you need to use partial instead of just using merge here is because the final map is the merged result of the maps from left-to-right. Your solution works if you want the values from the JSON map to take precedence.

(update-in req [:params]
  (partial merge (json/parse-string (slurp (:body req)) true)))
1
Dax Fohl On

Got it. assoc just works for one element so you have to put everything under the :backbone umbrella. To push all the JSON elements into the params, you have to use merge. So change the 4th line to:

(update-in req [:params] merge (json/parse-string (slurp (:body req)) true))
0
David Kay On

If you don't mind pulling in another dependency, you can use the ring-middleware-format library.

Instructions:

  • Add [ring-middleware-format "0.1.1"] to your project.clj

  • and then in your server.clj, add the following code:

Code:

(:require [ring.middleware.format-params :as format-params])

(server/add-middleware format-params/wrap-json-params)

(defn -main [& m]
; Start the server...
)

Now any incoming JSON will be available to use just like form POSTdata.