【问题标题】:Accessing POST json in clojure在 clojure 中访问 POST json
【发布时间】:2013-01-20 10:55:24
【问题描述】:

编辑 - source code is on github 如果您有兴趣。谢谢


对于如何访问已发布到 clojure 中的 url 的 json 数据,我有点困惑;我似乎无法让它工作。

这是我的路线:

(cc/POST "/add" 
request
(str ": " request))

我不完全确定我必须用什么代替 request - 我刚刚在网上看到一些博客并尝试关注它,但无法让它发挥作用。

这是我尝试发帖的方式:(来自fiddler

注意:图片中的请求头端口不同;这是一个错误,我试图弄乱该数据以查看其内容,因此请忽略上图中的那部分

在 curl 中,我只是这样做:

curl -X POST -H "Content-Type: application/json" -d '{"foo":"bar","baz":5}' 
     http://localhost:3005/add

看起来 clojure 根本没有收到我发布的 json 数据。

以下是请求变量包含的内容:

: {:scheme :http, :query-params {}, :form-params {}, :request-method :post, 
   :query-string nil, :route-params {}, :content-type "\"application/json\"", 
   :uri "/event", :server-name "localhost", :params {}, 
   :headers {"user-agent" "Fiddler", "content-type" "\"application/json\"", 
          "content-length" "23", "host" "localhost:3005"}, 
   :content-length 23, :server-port 3005, :character-encoding nil, :body #}

如你所见,所有params都是空的……

我正在使用 compojure 和 cheshire - 我可以将数据转换为 json 并将它们返回到 GET 路由中。我需要弄清楚如何传递 json 并将其转换为 clojure 数据。

谢谢

【问题讨论】:

  • 发布的数据应该是{"foo" : "bar" , "baz" : 5}而不是'{"foo" : "bar" , "baz" : 5}'
  • @Ankur,试过了,没什么区别

标签: json post clojure compojure


【解决方案1】:

这是因为 :params 由处理“表单编码”主体的环形中间件填充。

您可以使用 ring-json 将您的应用程序包装到这个其他中间件中。它将解析 JSON 正文并相应地填充 :params。 (https://github.com/ring-clojure/ring-json)

【讨论】:

  • 嗨,我正在使用 cheshire 在响应时转换为 json,查看 ring,我完全删除了 cheshire 并用 github 上提到的 ring 替换了它。现在没有任何作用,页面只是返回0 内容长度(以前的响应是 json),甚至没有设置内容类型.. 是否有教程或任何东西从零开始解释这一点?抱歉,我是一个绝对的初学者,目前无法很好地使用 clojure
  • 问题似乎是大多数博客似乎已经过时并且使用的旧代码与 ring-json 不在同一个命名空间中。例如:[ring.middleware.format-params :only [wrap-json-params]] from stackoverflow.com/questions/13150297/…
【解决方案2】:

这是一个可以满足您要求的示例。代码取自project。在 README 中,您将看到它支持的一些访问模式。代码有点乱,但应该能说明如何做到这一点。

(ns poky.protocol.http.jdbc.text
  (:require [poky.kv.core :as kv]
    (compojure [core :refer :all]
               [route :as route]
               [handler :as handler])
    [ring.util.response :refer [response not-found]]
    (ring.middleware [format-response :as format-response ]
                     [format-params :as format-params])
    [cheshire.core :as json]
    [ring.middleware.stacktrace :as trace]))

;
; curl -d"some data" -H'Content-Type: application/text' -v -X PUT http://localhost:8080/xxx
; curl -d'{"bla":"bar"}' -H'Content-Type: application/json' -v -X PUT http://localhost:8080/bla

(def valid-key-regex #"[\d\w-_.,]+")

; FIXME: this should be split- one fn for get, one for mget
(defn- wrap-get
  [kvstore ks params headers body]
  (response 
    (let [eks (clojure.string/split ks #",")
          nks (count eks)
          multi (> nks 1)
          ret (if multi (kv/mget* kvstore eks) (kv/get* kvstore ks))]
    (condp = (get headers "accept")
      "application/json" ret
      "text/plain" (if multi (throw (Exception. "Multi get unsupported with Accept: text/plain")) (get ret ks))
      ret))))



(defn- wrap-put
  [kvstore ks params headers body]
  (if (and 
        (= (get headers "content-type") "application/json")
        (get params (keyword ks) nil))
    (kv/set* kvstore ks (get params (keyword ks)))
    (kv/set* kvstore ks body))
  (response ""))

(defn api
  [kvstore]
  (let [api-routes
        (routes
          (GET ["/:ks" :ks valid-key-regex] {{:keys [ks] :as params} :params body :body headers :headers}
               (wrap-get kvstore ks params headers body))
          (PUT ["/:ks" :ks valid-key-regex] {{:keys [ks] :as params} :params 
                                             body :body body-params :body-params headers :headers} 
               (let [body (slurp body)
                     body (if (empty? body) body-params body)]
                 (wrap-put kvstore ks params headers body))))]

    (-> (handler/api api-routes)
        (format-params/wrap-format-params
          :predicate format-params/json-request?
          :decoder #(json/parse-string % true)
          :charset format-params/get-or-guess-charset)
        (format-response/wrap-format-response
          :predicate format-response/serializable?
          :encoders [(format-response/make-encoder json/encode "application/json")
                     (format-response/make-encoder identity "text/plain")]
          :charset "utf-8")
        trace/wrap-stacktrace)))

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    只是对先前答案的更新,现在足以将带有格式列表的 formats 键添加到您的处理程序中。

    类似

    (def app (noir.util.middleware/app-handler 
               [your-routes]
               :formats [:json-kw]))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 2016-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-06
      • 1970-01-01
      相关资源
      最近更新 更多