ceth
ceth

Reputation: 45285

Get Clojure map from POST request

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

Answers (3)

Piotrek Bzdyl
Piotrek Bzdyl

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

guijob
guijob

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

Alan Thompson
Alan Thompson

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

Related Questions