如何使用 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!
键关联的函数不是处理程序函数。解放者文档称其为操作函数。
动作函数 按键:p ost!、:p ut!和:d elete!提供积分 非常适合制定副作用。在评估它们时 与决策函数一样,布尔值没有影响,下一个 决策步骤是恒定的。上下文更新的工作方式与 决策函数。
因此,您无法直接从与:post!
关联的函数生成 http 响应。
与:post!
键关联的函数可以返回某些内容,并且某些内容将合并到上下文中。
上下文更新的工作方式与决策函数完全相同。
然后,处理程序函数稍后可以将该内容从上下文中提取出来,并使用它来形成 http 响应。 与这些键关联的任何一个处理程序函数都可能随后执行::handle-ok
、:handle-created
、:handle-no-content
、:handle-see-other
、:handle-multiple-representations
此决策图确定将执行哪个处理程序。
最好只使用指向新创建的资源而不使用正文的位置标头进行响应,但这里有一个创建具有 JSON 正文和 201 状态的响应的示例。
(POST "/foo" [] (resource :allowed-methods [:post]
:available-media-types ["application/json"]
:handle-created {:created "ok"}))
尝试一下:
curl -X POST "localhost/foo"
{"created":"ok"}
您可以在 Liberator 的 project.clj 文件中查看使用哪个 JSON 库。如果你想自己生成JSON字符串,你可以这样做:
:handle-created (fn [ctx] (liberator.representation/ring-response
{:status 201 :body "{created:"ok"}"}))
这里提到
这就是我的做法 - 它似乎有效,但我才刚刚开始使用 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 正在使用默认的句柄创建的处理程序,该处理程序仅返回标头。要返回自己的 json,您需要定义处理程序。
请注意,我没有使用 post! 方法。这是因为在此示例中,我实际上并没有创建某种新对象/项,例如将记录添加到某种存储中。如果你这样做,你可能会做的是使用post!添加记录并定义句柄创建,然后获取新记录(可能使用其他新字段,例如记录 ID 或时间戳等)并返回它。
我使用 :格式不正确? 和句柄格式不正确来执行基本错误检查。如果 :格式不正确?返回 true,调用句柄格式错误的标头,这将在 JSON 正文中返回错误状态和错误消息。我发现以 json 格式返回您的错误很有帮助,这样您就可以在客户端一致地处理所有内容。
我的处理程序和中间件定义如下。请注意,由于我同时提供应用程序和 api 路由,它们有点复杂,因为我希望将一些中间件应用于某些路由,而将其他中间件应用于其他路由。环/环默认值中还有一个小错误,一旦修复,将修改内容,因为目前我无法使用包装默认值站点 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)))
代码201 created
用于返回指向正文中新创建的资源的链接以及位置标头。如果要在正文中返回新创建的资源,则应使用 200 ok
。默认情况下,解放者将在开机自检后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))))
我建议 Ceshire 解析并生成 JSON。