Reputation: 45285
Here is my code:
(ns cowl.server
(:use compojure.core)
(:require [ring.adapter.jetty :as jetty]
[ring.middleware.params :as params]
[ring.middleware.json :refer [wrap-json-response]]
[ring.util.response :refer [response]]
[clojure.data.json :as json]
[cowl.db :as db]))
(defroutes main-routes
(POST "/api/news/as-read" { body :body }
(str (json/read-str (slurp body))))))
(def app
(-> main-routes
wrap-json-response))
(defn serve []
(jetty/run-jetty app {:port 3000}))
If I post this JSON: { "name": "demas" }
I get {"name" "demas"}
. But this is not a Clojure map.
I need something like (:name (json/read-str (slurp body)))
. How can I get it ?
Upvotes: 0
Views: 1258
Reputation: 13175
Instead of handling body JSON parsing by yourself, you can use ring.middleware.json/wrap-json-body
. Just modify your middleware setup:
(def app
(-> main-routes
wrap-json-response
(wrap-json-body {:keywords? true})))
and your request :body
will become JSON parsed to Clojure data.
Upvotes: 5
Reputation: 4488
You can use :key-fn function as well:
(json/read-str (return :body)
:key-fn keyword)
Doing this you will parse your JSON to default map syntax.
Upvotes: 1
Reputation: 29958
You may wish to use the keywordize-keys
function:
http://clojuredocs.org/clojure.walk/keywordize-keys
(ns xyz.core
(:require [clojure.walk :as walk]))
(walk/keywordize-keys {"a" 1 "b" 2})
;;=> {:a 1 :b 2}
You will probably also find that the Cheshire lib is the best way to process JSON in Clojure: https://github.com/dakrone/cheshire#decoding
;; parse some json
(parse-string "{\"foo\":\"bar\"}")
;; => {"foo" "bar"}
;; parse some json and get keywords back
(parse-string "{\"foo\":\"bar\"}" true) ; true -> want keyword keys
;; => {:foo "bar"}
;; parse some json and munge keywords with a custom function
(parse-string "{\"foo\":\"bar\"}" (fn [k] (keyword (.toUpperCase k))))
;; => {:FOO "bar"}
Upvotes: 1