为什么在使用 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 环形中间件需要正确设置内容类型,所以也许这就是为什么在您的情况下结构未正确解析的原因?