Search code examples
clojurenoir

How to get JSON post data in Noir


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?


Solution

  • 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)))