为什么在使用 ring json 中间件时必须展平嵌套 JSON
Why do I have to flatten nested JSON when using the ring json middleware
我一直在用 ring 和 compojure 编写一个 clojure 应用程序。我正在使用 ring.middleware.json
中间件来处理 JSON 所以我不必在我的代码中自己序列化和反序列化它。
这个中间件似乎只有在以扁平格式给出时才能正确解析嵌套 JSON,例如,如果我想 POST 嵌套数据到 API 路由,我必须编码它是:
{"task" : 1,
"success" : false,
"files[0][type]" : "log",
"files[0][sha256]" : "adef5c",
"files[0][url]" : "s3://url"}
而不是,在我看来,更标准 JSON:
{"task" : 1,
"success" : false,
"files" : [{"type" : "log", "sha256" : "adef5c", "url": "s3://url"}]}
这是缩进的还是标准的嵌套发帖方式 JSON?这是我的中间件堆栈:
(defn middleware [handler]
(-> handler
(wrap-json-response)
(wrap-with-logger)
(api)))
这是 post 的完整 Clojure 示例,并获取处理 JSON 或 return 的路由 JSON:
(ns ring-app.core
(:require [ring.adapter.jetty :as jetty]
[compojure.core :as compojure]
[ring.middleware.keyword-params :refer [wrap-keyword-params]]
[ring.middleware.json :refer [wrap-json-response wrap-json-body]]
[ring.util.http-response :as response]
[clojure.pprint :refer [pprint]]
[ring.middleware.reload :refer [wrap-reload]]))
(defn json-get [request]
(response/ok
{"task" 1
"success" false
"files" [{"type" "log" "sha256" "adef5c" "url" "s3://url"}]}))
(defn json-post [request]
(let [bpdy (:body request)]
(prn bpdy)
(response/ok bpdy)))
(compojure/defroutes handler_
(compojure/GET "/get" request json-get)
(compojure/POST "/post" request json-post))
(defn wrap-nocache [handler]
(fn [request]
(-> request
handler
(assoc-in [:headers "Pragma"] "no-cache"))))
(def handler
(-> #'handler_ wrap-nocache wrap-reload wrap-json-response wrap-json-body ) )
获取端点return嵌套结构:
curl http://localhost:3000/get
; {"task":1,"success":false,"files":[{"type":"log","sha256":"adef5c","url":"s3://url"}]}
并且 POST 端点解析 json 并创建一个 Clojure 数据结构:
curl -X post -d '{"task":1,"success":false,"files":[{"type":"log","sha256":"adef5c","url":"s3://url"}]}' -H "Accept: application/json" -H "Content-type: application/json" http://localhost:3000/post
; {"task":1,"success":false,"files":[{"type":"log","sha256":"adef5c","url":"s3://url"}]}
这是 JSON->CLJ->JSON
的往返
json 环形中间件需要正确设置内容类型,所以也许这就是为什么在您的情况下结构未正确解析的原因?
我一直在用 ring 和 compojure 编写一个 clojure 应用程序。我正在使用 ring.middleware.json
中间件来处理 JSON 所以我不必在我的代码中自己序列化和反序列化它。
这个中间件似乎只有在以扁平格式给出时才能正确解析嵌套 JSON,例如,如果我想 POST 嵌套数据到 API 路由,我必须编码它是:
{"task" : 1,
"success" : false,
"files[0][type]" : "log",
"files[0][sha256]" : "adef5c",
"files[0][url]" : "s3://url"}
而不是,在我看来,更标准 JSON:
{"task" : 1,
"success" : false,
"files" : [{"type" : "log", "sha256" : "adef5c", "url": "s3://url"}]}
这是缩进的还是标准的嵌套发帖方式 JSON?这是我的中间件堆栈:
(defn middleware [handler]
(-> handler
(wrap-json-response)
(wrap-with-logger)
(api)))
这是 post 的完整 Clojure 示例,并获取处理 JSON 或 return 的路由 JSON:
(ns ring-app.core
(:require [ring.adapter.jetty :as jetty]
[compojure.core :as compojure]
[ring.middleware.keyword-params :refer [wrap-keyword-params]]
[ring.middleware.json :refer [wrap-json-response wrap-json-body]]
[ring.util.http-response :as response]
[clojure.pprint :refer [pprint]]
[ring.middleware.reload :refer [wrap-reload]]))
(defn json-get [request]
(response/ok
{"task" 1
"success" false
"files" [{"type" "log" "sha256" "adef5c" "url" "s3://url"}]}))
(defn json-post [request]
(let [bpdy (:body request)]
(prn bpdy)
(response/ok bpdy)))
(compojure/defroutes handler_
(compojure/GET "/get" request json-get)
(compojure/POST "/post" request json-post))
(defn wrap-nocache [handler]
(fn [request]
(-> request
handler
(assoc-in [:headers "Pragma"] "no-cache"))))
(def handler
(-> #'handler_ wrap-nocache wrap-reload wrap-json-response wrap-json-body ) )
获取端点return嵌套结构:
curl http://localhost:3000/get
; {"task":1,"success":false,"files":[{"type":"log","sha256":"adef5c","url":"s3://url"}]}
并且 POST 端点解析 json 并创建一个 Clojure 数据结构:
curl -X post -d '{"task":1,"success":false,"files":[{"type":"log","sha256":"adef5c","url":"s3://url"}]}' -H "Accept: application/json" -H "Content-type: application/json" http://localhost:3000/post
; {"task":1,"success":false,"files":[{"type":"log","sha256":"adef5c","url":"s3://url"}]}
这是 JSON->CLJ->JSON
的往返json 环形中间件需要正确设置内容类型,所以也许这就是为什么在您的情况下结构未正确解析的原因?