Skip to content

Commit

Permalink
Merge pull request #68 from CHNB128/add-key-fn
Browse files Browse the repository at this point in the history
Add key-fn option
  • Loading branch information
weavejester authored Oct 18, 2020
2 parents efb5bc8 + a7a3d64 commit f2facdf
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 8 deletions.
15 changes: 9 additions & 6 deletions src/ring/middleware/json.clj
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
(if-let [type (get-in request [:headers "content-type"])]
(not (empty? (re-find #"^application/(.+\+)?json" type)))))

(defn- read-json [request & [{:keys [keywords? bigdecimals?]}]]
(defn- read-json [request & [{:keys [keywords? bigdecimals? key-fn]}]]
(if (json-request? request)
(if-let [^InputStream body (:body request)]
(let [^String encoding (or (character-encoding request)
"UTF-8")
body-reader (java.io.InputStreamReader. body encoding)]
(binding [parse/*use-bigdecimals?* bigdecimals?]
(try
[true (json/parse-stream body-reader keywords?)]
[true (json/parse-stream body-reader (or key-fn keywords?))]
(catch com.fasterxml.jackson.core.JsonParseException ex
[false nil])))))))

Expand All @@ -34,8 +34,8 @@
(defn json-body-request
"Parse a JSON request body and assoc it back into the :body key. Returns nil
if the JSON is malformed. See: wrap-json-body."
[request {:keys [keywords? bigdecimals?]}]
(if-let [[valid? json] (read-json request {:keywords? keywords? :bigdecimals? bigdecimals?})]
[request options]
(if-let [[valid? json] (read-json request options)]
(if valid? (assoc request :body json))
request))

Expand All @@ -46,6 +46,7 @@
Accepts the following options:
:key-fn - function that will be applied to each key
:keywords? - true if the keys of maps should be turned into keywords
:bigdecimals? - true if BigDecimals should be used instead of Doubles
:malformed-response - a response map to return when the JSON is malformed"
Expand Down Expand Up @@ -74,8 +75,8 @@
"Parse the body of JSON requests into a map of parameters, which are added
to the request map on the :json-params and :params keys. Returns nil if the
JSON is malformed. See: wrap-json-params."
[request {:keys [bigdecimals?]}]
(if-let [[valid? json] (read-json request {:bigdecimals? bigdecimals?})]
[request options]
(if-let [[valid? json] (read-json request options)]
(if valid? (assoc-json-params request json))
request))

Expand All @@ -85,6 +86,7 @@
Accepts the following options:
:key-fn - function that will be applied to each key
:bigdecimals? - true if BigDecimals should be used instead of Doubles
:malformed-response - a response map to return when the JSON is malformed
Expand Down Expand Up @@ -130,6 +132,7 @@
Accepts the following options:
:key-fn - function that will be applied to each key
:pretty - true if the JSON should be pretty-printed
:escape-non-ascii - true if non-ASCII characters should be escaped with \\u
:stream? - true to create JSON body as stream rather than string"
Expand Down
27 changes: 25 additions & 2 deletions test/ring/middleware/test/json.clj
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
:body (string-input-stream "{\"foo\": \"bar\"}")}
response (handler request)]
(is (= {"foo" "bar"} (:body response)))))

(testing "custom json body"
(let [request {:headers {"content-type" "application/vnd.foobar+json; charset=UTF-8"}
:body (string-input-stream "{\"foo\": \"bar\"}")}
Expand Down Expand Up @@ -45,6 +45,13 @@
response (handler request)]
(is (= {"foo" "你好"} (:body response))))))

(let [handler (wrap-json-body identity {:key-fn (fn [k] (.toUpperCase (name k)))})]
(testing "key-fn"
(let [request {:headers {"content-type" "application/json; charset=UTF-8"}
:body (string-input-stream "{\"foo\": \"bar\"}")}
response (handler request)]
(is (= {"FOO" "bar"} (:body response))))))

(let [handler (wrap-json-body identity {:keywords? true})]
(testing "keyword keys"
(let [request {:headers {"content-type" "application/json"}
Expand Down Expand Up @@ -146,7 +153,7 @@
(is (= (get-in @response [:body :bigdecimals]) true)))))))

(deftest test-json-params
(let [handler (wrap-json-params identity)]
(let [handler (wrap-json-params identity)]
(testing "xml body"
(let [request {:headers {"content-type" "application/xml"}
:body (string-input-stream "<xml></xml>")
Expand All @@ -164,6 +171,15 @@
(is (= {"id" 3, "foo" "bar"} (:params response)))
(is (= {"foo" "bar"} (:json-params response)))))

(testing "key-fn"
(let [request {:headers {"content-type" "application/json; charset=UTF-8"}
:body (string-input-stream "{\"foo\": \"bar\"}")
:params {"id" 3}}
handler (wrap-json-params identity {:key-fn (fn [k] (.toUpperCase (name k)))})
response (handler request)]
(is (= {"id" 3, "FOO" "bar"} (:params response)))
(is (= {"FOO" "bar"} (:json-params response)))))

(testing "json body with bigdecimals"
(let [handler (wrap-json-params identity {:bigdecimals? true})
request {:headers {"content-type" "application/json; charset=UTF-8"}
Expand Down Expand Up @@ -313,6 +329,13 @@
(is (= (get-in response [:headers "Content-Type"]) "application/json; charset=utf-8"))
(is (= (:body response) "[\"foo\",\"bar\"]"))))

(testing "key-fn"
(let [handler (constantly {:status 200 :headers {} :body {:foo "bar" :baz "quz"}})
response ((wrap-json-response handler {:key-fn (fn [k] (.toUpperCase (name k)))}) {})]
(is (= (get-in response [:headers "Content-Type"]) "application/json; charset=utf-8"))
(is (or (= "{\"FOO\":\"bar\",\"BAZ\":\"quz\"}" (:body response))
(= "{\"BAZ\":\"quz\",\"FOO\":\"bar\"}" (:body response))))))

(testing "list body"
(let [handler (constantly {:status 200 :headers {} :body '(:foo :bar)})
response ((wrap-json-response handler) {})]
Expand Down

0 comments on commit f2facdf

Please sign in to comment.