如何从帖子返回json数据! clojure解放器中的处理程序?

时间:2015-01-23 10:08:36

标签: clojure liberator

如何使用Clojure Liberator返回json-data?此代码不起作用:

(defresource poster []
         :allowed-methods [:post :options]
         :available-media-types ["application/json"]
         :post!      (fn [ctx] (println "posting..."))
         :handle-created (fn [ctx] {:created "ok"}))

应该在post之后调用handle-created吗?

3 个答案:

答案 0 :(得分:3)

:post!键关联的函数不是处理函数。 Liberator文档将其称为动作函数。

  

动作功能键:post!,:put!并且:删除!提供积分   适合制定副作用。虽然他们被评估   像决策函数一样,布尔值没有效果,下一个   决策步骤是不变的。上下文更新的工作方式与   决策职能。

因此,您无法直接从与:post!相关联的函数生成http响应。

:post!键关联的函数可能会返回一些内容,并且某些内容会合并到上下文中。

  

上下文更新与决策函数完全相同。

然后处理程序函数可以稍后将某些内容从上下文中拉出来并使用它来形成http响应。与这些密钥关联的任何一个处理函数都可能随后执行::handle-ok:handle-created:handle-no-content:handle-see-other:handle-multiple-representations

decision graph确定将执行哪个处理程序。

最好只使用指向新创建的资源且没有正文的位置标题进行响应,但这里是创建具有JSON正文和201状态的响应的一个示例。

(POST "/foo" [] (resource :allowed-methods [:post]
                           :available-media-types ["application/json"]
                           :handle-created {:created "ok"}))

尝试一下:

curl -X POST "localhost/foo" 
{"created":"ok"}

您可以在其project.clj文件中查看哪个JSON库Liberator使用。如果你想自己生成JSON字符串,你可以这样做:

:handle-created (fn [ctx] (liberator.representation/ring-response 
                          {:status 201 :body "{created:\"ok\"}"}))

提到here

答案 1 :(得分:1)

这就是我这样做的方式 - 它似乎有用,但我只是刚开始使用Liberator,所以可能有更好或更正确的方法来做到这一点!

我认为你需要的是一个句柄创建的处理程序。例如 -

(defresource shopping-calc
  :allowed-methods [:post]
  :available-media-types ["application/json"]
  :malformed? (fn [context]
                (let [params (get-in context [:request :params])]
                  (or (empty? params)
                      (is-malformed? params))))
  :handle-malformed (fn [context]
                      (let [params (get-in context [:request :params])]
                        (generate-string (handle-malformed-calc params))))
  :handle-created (fn [context]
                    (let [params (get-in context [:request :params])]
                      (generate-string (calculate-total params)))))

我有一个像这样的处理程序创建的处理程序

(defn calculate-total [params]
  {:total (calc params)})

我也使用ring / json中间件,在我的开发环境中,添加了解放器跟踪工具。 Liberator跟踪工具非常方便,因为它会在响应中添加标题,以显示Liberator的决策点。所以,对于你的问题,它可能会显示Liberator正在使用默认的句柄创建的处理程序,它只返回标题。要返回自己的json,需要定义处理程序。

请注意,我没有使用帖子!方法。这是因为在这个例子中,我实际上并没有创建某种新的对象/项目,例如将记录添加到某种商店。如果你这样做,你可能会做的就是发帖!添加记录并定义句柄创建然后获取新记录(可能与其他新字段,如记录ID或时间戳等)并返回它。

我使用:畸形?并且处理错误以执行基本错误检查。如果:畸形?返回true,调用handle-malformed标头,返回错误状态和json正文中的错误消息。我发现在json中返回错误也很有帮助,这样你就可以在客户端一致地处理所有事情。

我的处理程序和中间件定义如下。请注意,由于我提供了应用程序和api路由,因为我希望将某些中间件应用于某些路由,将其他中间件应用于其他路由,因此它们会更复杂一些。在ring / ring-defaults中还有一个小错误,一旦修复,将修改内容,因为目前我无法使用wrap-defaults site-api中间件。请注意包裹跟踪中间件。

(def app
  (if (env :dev)
    (routes (-> api-routes
                (wrap-reload)
                (wrap-routes wrap-json-params)
                (wrap-routes wrap-defaults api-defaults)
                (wrap-routes wrap-trace :header :ui))
            (-> app-routes
                (wrap-routes wrap-error-page)
                (wrap-routes wrap-exceptions)))
    (routes (-> api-routes
                (wrap-routes wrap-json-params)
                (wrap-routes wrap-defaults api-defaults))
            app-routes)))

答案 2 :(得分:1)

代码201 created用于返回正文中新创建的资源的链接以及Location标头。如果您想在正文中返回新创建的资源,则应使用200 ok。默认情况下,POST后204 no-content:respond-with-entity? true。您需要设置(defresource poster [] :allowed-methods [:post :options] :available-media-types ["application/json"] :malformed? (fn [ctx] [false {::resource (parse-json (get-in ctx [:request :body]))}]) :post! (fn [ctx] (persist (::resource ctx))) :handle-ok (fn [ctx] (generate-json (::resource ctx))))

您的资源定义如下:

{{1}}

我建议Liberator will end up解析并生成JSON。