Clojure 嵌套 json 响应
Clojure nested json response
我是 clojure 的新手,我正在尝试制作一个带有 3 个端点的简单 API。
我正在尝试实现一个端点,它将获取查询的每一行并将其放入 json。
所以我有一个 SQLite 数据库。例如,这些是我的条目:
{:timestamp 2020-09-11 14:29:30, :lat 36.0, :long 36.0, :user michav}
{:timestamp 2020-09-11 14:31:47, :lat 36.0, :long 36.0, :user michav}
所以我想要一个像下面这样的 json 响应:
{:get
:status 200
:body {:timestamp "2020-09-11 14:29:30"
:lat 36.0
:long 36.0
:user "michav"}
{:timestamp "2020-09-11 14:31:47"
:lat 36.0
:long 36.0
:user "michav"}
}
}
这是我的代码,我正在尝试修复它以获得上述结果。
(def db
{:classname "org.sqlite.JDBC"
:subprotocol "sqlite"
:subname "db/database.db"
})
(defn getparameter [req pname] (get (:params req) pname))
(defn output
"execute query and return lazy sequence"
[]
(query db ["select * from traffic_users"]))
(defn print-result-set
"prints the result set in tabular form"
[result-set]
(doseq [row result-set]
(println row)))
(defn request-example [req]
(response {:get {:status 200
:body (-> (doseq [row output]
{:timestamp (getparameter row :timestamp) :lat (getparameter row :lat) :long (getparameter row :long) :user (getparameter row :user)} ))
}}))
(defroutes my_routes
(GET "/request" [] request-example)
(route/resources "/"))
(def app (-> #'my_routes wrap-cookies wrap-keyword-params wrap-params wrap-json-response))
我遇到的错误如下:
java.lang.IllegalArgumentException: Don't know how to create ISeq from: mybank.core$output
RT.java:557 clojure.lang.RT.seqFrom
RT.java:537 clojure.lang.RT.seq
core.clj:137 clojure.core/seq
core.clj:137 clojure.core/seq
core.clj:65 mybank.core/request-example[fn]
core.clj:65 mybank.core/request-example
core.clj:63 mybank.core/request-example
response.clj:47 compojure.response/eval1399[fn]
response.clj:7 compojure.response/eval1321[fn]
core.clj:158 compojure.core/wrap-response[fn]
core.clj:128 compojure.core/wrap-route-middleware[fn]
core.clj:137 compojure.core/wrap-route-info[fn]
core.clj:146 compojure.core/wrap-route-matches[fn]
core.clj:185 compojure.core/routing[fn]
core.clj:2701 clojure.core/some
core.clj:2692 clojure.core/some
core.clj:185 compojure.core/routing
core.clj:182 compojure.core/routing
RestFn.java:139 clojure.lang.RestFn.applyTo
core.clj:667 clojure.core/apply
core.clj:660 clojure.core/apply
core.clj:192 compojure.core/routes[fn]
Var.java:384 clojure.lang.Var.invoke
cookies.clj:171 ring.middleware.cookies/wrap-cookies[fn]
keyword_params.clj:32 ring.middleware.keyword-params/wrap-keyword-params[fn]
params.clj:57 ring.middleware.params/wrap-params[fn]
json.clj:42 ring.middleware.json/wrap-json-response[fn]
Var.java:384 clojure.lang.Var.invoke
reload.clj:18 ring.middleware.reload/wrap-reload[fn]
stacktrace.clj:17 ring.middleware.stacktrace/wrap-stacktrace-log[fn]
stacktrace.clj:80 ring.middleware.stacktrace/wrap-stacktrace-web[fn]
jetty.clj:27 ring.adapter.jetty/proxy-handler[fn]
(Unknown Source) ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$ff19274a.handle
HandlerWrapper.java:127 org.eclipse.jetty.server.handler.HandlerWrapper.handle
Server.java:500 org.eclipse.jetty.server.Server.handle
HttpChannel.java:386 org.eclipse.jetty.server.HttpChannel.lambda$handle
HttpChannel.java:562 org.eclipse.jetty.server.HttpChannel.dispatch
HttpChannel.java:378 org.eclipse.jetty.server.HttpChannel.handle
HttpConnection.java:270 org.eclipse.jetty.server.HttpConnection.onFillable
AbstractConnection.java:311 org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded
FillInterest.java:103 org.eclipse.jetty.io.FillInterest.fillable
ChannelEndPoint.java:117 org.eclipse.jetty.io.ChannelEndPoint.run
EatWhatYouKill.java:336 org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask
EatWhatYouKill.java:313 org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce
EatWhatYouKill.java:171 org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce
EatWhatYouKill.java:135 org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce
QueuedThreadPool.java:806 org.eclipse.jetty.util.thread.QueuedThreadPool.runJob
QueuedThreadPool.java:938 org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run
(Unknown Source) java.lang.Thread.run
你的错误在这一行:
(doseq [row output] ...
错误信息
Don't know how to create ISeq from: mybank.core$output
给出线索。变量 output
是函数,而不是 doseq
期望的序列。您打算调用 output
函数,因此您需要使用括号来创建函数调用,例如:
(doseq [row (output)] ...
更新
您需要包含外部库以在 EDN 数据和 JSON 字符串之间进行转换。我最喜欢的方式是我自己的图书馆Tupelo Clojure。像这样使用它:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(let [data [{:timestamp "2020-09-11 14:29:30", :lat 36.0, :long 36.0, :user "michav"}
{:timestamp "2020-09-11 14:31:47", :lat 36.0, :long 36.0, :user "michav"}]]
(println (edn->json data)))
结果:
[{"timestamp":"2020-09-11 14:29:30","lat":36.0,"long":36.0,"user":"michav"},
{"timestamp":"2020-09-11 14:31:47","lat":36.0,"long":36.0,"user":"michav"}]
您需要在 project.clj
:
中添加这样一行
[tupelo "20.08.27"]
请 also see this template project 获取简单的入门方法。享受吧!
我是 clojure 的新手,我正在尝试制作一个带有 3 个端点的简单 API。 我正在尝试实现一个端点,它将获取查询的每一行并将其放入 json。 所以我有一个 SQLite 数据库。例如,这些是我的条目:
{:timestamp 2020-09-11 14:29:30, :lat 36.0, :long 36.0, :user michav}
{:timestamp 2020-09-11 14:31:47, :lat 36.0, :long 36.0, :user michav}
所以我想要一个像下面这样的 json 响应:
{:get
:status 200
:body {:timestamp "2020-09-11 14:29:30"
:lat 36.0
:long 36.0
:user "michav"}
{:timestamp "2020-09-11 14:31:47"
:lat 36.0
:long 36.0
:user "michav"}
}
} 这是我的代码,我正在尝试修复它以获得上述结果。
(def db
{:classname "org.sqlite.JDBC"
:subprotocol "sqlite"
:subname "db/database.db"
})
(defn getparameter [req pname] (get (:params req) pname))
(defn output
"execute query and return lazy sequence"
[]
(query db ["select * from traffic_users"]))
(defn print-result-set
"prints the result set in tabular form"
[result-set]
(doseq [row result-set]
(println row)))
(defn request-example [req]
(response {:get {:status 200
:body (-> (doseq [row output]
{:timestamp (getparameter row :timestamp) :lat (getparameter row :lat) :long (getparameter row :long) :user (getparameter row :user)} ))
}}))
(defroutes my_routes
(GET "/request" [] request-example)
(route/resources "/"))
(def app (-> #'my_routes wrap-cookies wrap-keyword-params wrap-params wrap-json-response))
我遇到的错误如下:
java.lang.IllegalArgumentException: Don't know how to create ISeq from: mybank.core$output
RT.java:557 clojure.lang.RT.seqFrom
RT.java:537 clojure.lang.RT.seq
core.clj:137 clojure.core/seq
core.clj:137 clojure.core/seq
core.clj:65 mybank.core/request-example[fn]
core.clj:65 mybank.core/request-example
core.clj:63 mybank.core/request-example
response.clj:47 compojure.response/eval1399[fn]
response.clj:7 compojure.response/eval1321[fn]
core.clj:158 compojure.core/wrap-response[fn]
core.clj:128 compojure.core/wrap-route-middleware[fn]
core.clj:137 compojure.core/wrap-route-info[fn]
core.clj:146 compojure.core/wrap-route-matches[fn]
core.clj:185 compojure.core/routing[fn]
core.clj:2701 clojure.core/some
core.clj:2692 clojure.core/some
core.clj:185 compojure.core/routing
core.clj:182 compojure.core/routing
RestFn.java:139 clojure.lang.RestFn.applyTo
core.clj:667 clojure.core/apply
core.clj:660 clojure.core/apply
core.clj:192 compojure.core/routes[fn]
Var.java:384 clojure.lang.Var.invoke
cookies.clj:171 ring.middleware.cookies/wrap-cookies[fn]
keyword_params.clj:32 ring.middleware.keyword-params/wrap-keyword-params[fn]
params.clj:57 ring.middleware.params/wrap-params[fn]
json.clj:42 ring.middleware.json/wrap-json-response[fn]
Var.java:384 clojure.lang.Var.invoke
reload.clj:18 ring.middleware.reload/wrap-reload[fn]
stacktrace.clj:17 ring.middleware.stacktrace/wrap-stacktrace-log[fn]
stacktrace.clj:80 ring.middleware.stacktrace/wrap-stacktrace-web[fn]
jetty.clj:27 ring.adapter.jetty/proxy-handler[fn]
(Unknown Source) ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$ff19274a.handle
HandlerWrapper.java:127 org.eclipse.jetty.server.handler.HandlerWrapper.handle
Server.java:500 org.eclipse.jetty.server.Server.handle
HttpChannel.java:386 org.eclipse.jetty.server.HttpChannel.lambda$handle
HttpChannel.java:562 org.eclipse.jetty.server.HttpChannel.dispatch
HttpChannel.java:378 org.eclipse.jetty.server.HttpChannel.handle
HttpConnection.java:270 org.eclipse.jetty.server.HttpConnection.onFillable
AbstractConnection.java:311 org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded
FillInterest.java:103 org.eclipse.jetty.io.FillInterest.fillable
ChannelEndPoint.java:117 org.eclipse.jetty.io.ChannelEndPoint.run
EatWhatYouKill.java:336 org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask
EatWhatYouKill.java:313 org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce
EatWhatYouKill.java:171 org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce
EatWhatYouKill.java:135 org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce
QueuedThreadPool.java:806 org.eclipse.jetty.util.thread.QueuedThreadPool.runJob
QueuedThreadPool.java:938 org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run
(Unknown Source) java.lang.Thread.run
你的错误在这一行:
(doseq [row output] ...
错误信息
Don't know how to create ISeq from: mybank.core$output
给出线索。变量 output
是函数,而不是 doseq
期望的序列。您打算调用 output
函数,因此您需要使用括号来创建函数调用,例如:
(doseq [row (output)] ...
更新
您需要包含外部库以在 EDN 数据和 JSON 字符串之间进行转换。我最喜欢的方式是我自己的图书馆Tupelo Clojure。像这样使用它:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(let [data [{:timestamp "2020-09-11 14:29:30", :lat 36.0, :long 36.0, :user "michav"}
{:timestamp "2020-09-11 14:31:47", :lat 36.0, :long 36.0, :user "michav"}]]
(println (edn->json data)))
结果:
[{"timestamp":"2020-09-11 14:29:30","lat":36.0,"long":36.0,"user":"michav"},
{"timestamp":"2020-09-11 14:31:47","lat":36.0,"long":36.0,"user":"michav"}]
您需要在 project.clj
:
[tupelo "20.08.27"]
请 also see this template project 获取简单的入门方法。享受吧!