ring-clojure / ring-json Goto Github PK
View Code? Open in Web Editor NEWRing middleware for handling JSON
Ring middleware for handling JSON
There are some functions that might be useful, in general (e.g. https://github.com/ring-clojure/ring-json/blob/master/src/ring/middleware/json.clj#L7), but can't be used because they are private.
What is the rationale behind this? Why not make them public?
Is there a way to tell wrap-json-response to use custom encoders? I didn't see any option for custom encoders, and wonder if people have workarounds?
Cheers
qfz
Most of the times I use kebab-case
keys for maps. In JavaScript, kebab-case is not well supported and t is most common to use camelCase
for JSON object keys.
When writing REST API, mainly when the client is not implemented in Clojure, the body JSON object keys are camelCase and it will be nice to be able to convert it to kebab-case when serializing the request.
{"firstName":"John", "lastName":"Doe"} -> {:first-name: "John" :last-name "Doe"}
It will be helpful to provide some kind of key converter function (i.e :key-fn
) or provide a JSON serializer function as a dependency.
I hope it makes sense not only to me...
I have a usecase where I’m returning a large amount of data from a resultset, lazily. Using wrap response attempts to build the whole string on heap.
I have a hacked fork which uses generate-stream and an InputStream response to
be more parsimonious about resources.
Is this something you’d be interested in a PR for? If so I may clean what I have up and fix tests etc.
Specifically, when the malformed JSON is in an array.
It's easily demonstrated in a repl:
user> (def bad-json (cheshire.core/parse-string "[{\"foo\": 1 2}]"))
#'user/bad-json
user> (type bad-json)
clojure.lang.LazySeq
user> (first bad-json)
JsonParseException Unexpected character ('2' (code 50)): was expecting comma to separate Object entries
at [Source: (StringReader); line: 1, column: 13] com.fasterxml.jackson.core.JsonParser._constructError (JsonParser.java:1798)
The JsonParseException
isn't thrown until the lazy sequence is realized, which may not be until subsequent middleware or an endpoint.
Options could be:
Thoughts?
Hi @weavejester!
This Ring middleware lib has a good design — it's succinct (minimalistic codebase and API) and does one thing (read/write JSON from/to req/resp) and does it well (in terms of performance).
Still, it strongly depends on a particular JSON mapping implementation library, a Cheshire in this case. And while it is apparently the most popular library for this purpose, there are numerous projects out there that use its alternatives, be it another Jackson-based metosin/jsonista
or org.clojure/data.json
with zero external dependencies. And, I hope you agree, it makes sense to (re)use the same tool for the same tasks within the same project (possibly, with the same set of configs).
I understand what could have caused such a choice before (historical reasons), but wouldn't it be better to leave this choice to the user themselves nowadays? This can be achieved by abstracting from the specific implementation and dynamically linking any supported library from the current classpath (much alike the clj-http.client
does it when looks for Cheshire). We've achieved a similar goal in the Telegram Bot API client, so there's already a reference code anyone could review.
But for the ring-json
, the task is a bit trickier due to the use of streams API and passing the mapping parameters along the way. And I'd propose to: a) split different mapper-specific implementations into different namespaces/files, if this is at all possible, to keep the codebase clean, and b) test the performance degradation with JMH and, if it is substantial, leave this library as it is (backed by Cheshire), perhaps providing alternatives (backed by the other two mappers) as separate artifacts.
Like to hear your thoughts!
Cheers,
Mark
I came across the following oddity a few days ago: if you create two sets of routes, wrap them both individually with wrap-json-body
and them combine them, the first set work fine, but the second get nil
as the request body.
E.g. (using compojure)
(defroutes router-1
(POST "/test1" req (println (:body req))))
(defroutes router-2
(POST "/test2" req (println (:body req))))
(defroutes combined-router
(->
router-1
wrap-json-body)
(->
router-2
wrap-json-body))
POSTing json data to /test1
causes the body to be printed to the terminal, whereas posting the exact same to /test2
just prints nil.
I made a repo to test this at https://github.com/tgetgood/json-ring-test
Non greedy regex could be relatively slow in some cases
https://github.com/ring-clojure/ring-json/blob/master/src/ring/middleware/json.clj#L13
just add one '?' after first +
#"^application/(.+?\+)?json"
This option is only available to wrap-json-body
, but it seems sensible that it would also be applicable to wrap-json-params
.
when I post request include chinese word,param includes "??"
(defn- read-json [request & [{:keys [keywords? bigdecimals?]}]]
(if (json-request? request)
(if-let [body (:body request)]
(let [body-string (slurp body)]
On line 48 of json.cli :
(defn- assoc-json-params [request json]
(if (map? json)
(-> request
(assoc :json-params json)
(update-in [:params] merge json))
request))
The map?
mysteriously filters out perfectly valid JSON strings and arrays. Why is this so?
A recent change for #16 will now only provide the data in :json-params and :params when the JSON submitted with a request is an object.
I am working on a clojure implementation for JSON patch: and the specification states:
A JSON Patch document is a JSON [RFC4627] document that represents an array of objects. Each object represents a single operation to be applied to the target JSON document.
Of course, the media type is currently incompatible with the current regular expression for ring-json:
The "application/json-patch+json" media type is used to identify such
patch documents.
(defn- json-request? [request]
(if-let [type (:content-type request)]
(not (empty? (re-find #"^application/(vnd.+)?json" type)))))
To that end, there are a number of JSON media types proposed to the IANA that are not compatible with that particular regular expression.
I would be happy to submit a pull request for a modified regular expression if that would be well-received.
I also would like to discuss a slight modification of the code introduced for #16 that will only merge maps into request :params, but will enable arrays to be passed through to :json-params, or perhaps introduce :json-body or :json-array for when the incoming JSON is not an object.
Thoughts?
When posting a request with invalid JSON in the request body, a 500 status code is returned by the web server. I would've expected a 400 status code to be returned because the request could not be understood by the server due to malformed syntax (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1) rather than a 500 status code which indicates a server-side error.
From looking through ring-json's and Cheshire's source code, I can see that nothing seems to anticipate that malformed JSON could be presented for parsing. Sometimes third party clients have a mistake with the JSON they send to my web service and it would be nice to send them an appropriate response to indicate the error is on their end instead of mine.
Here's the request I sent (missing closing brace in the body is the malformed part):
$ curl -X POST -H "Content-Type: application/json" -d '{"foo": "bar"' -v http://localhost:3000/todos
* About to connect() to localhost port 3000 (#0)
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> POST /todos HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:3000
> Accept: */*
> Content-Type: application/json
> Content-Length: 13
>
* upload completely sent off: 13 out of 13 bytes
< HTTP/1.1 500 Server Error
< Date: Mon, 06 May 2013 00:59:40 GMT
< Content-Type: text/html;charset=ISO-8859-1
< Content-Length: 5720
< Server: Jetty(7.6.1.v20120215)
<
Here's the stack trace on the server:
Exception: com.fasterxml.jackson.core.JsonParseException: Unexpected end-of-input: expected close marker for OBJECT (from [Source: java.io.StringReader@1b556b61; line: 1, column: 0])
at [Source: java.io.StringReader@1b556b61; line: 1, column: 27]
JsonParser.java:1378 com.fasterxml.jackson.core.JsonParser._constructError
ParserMinimalBase.java:599 com.fasterxml.jackson.core.base.ParserMinimalBase._reportError
ParserMinimalBase.java:532 com.fasterxml.jackson.core.base.ParserMinimalBase._reportInvalidEOF
ParserBase.java:479 com.fasterxml.jackson.core.base.ParserBase._handleEOF
ReaderBasedJsonParser.java:1679 com.fasterxml.jackson.core.json.ReaderBasedJsonParser._skipWSOrEnd
ReaderBasedJsonParser.java:561 com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken
parse.clj:42 cheshire.parse/parse*
parse.clj:61 cheshire.parse/parse
core.clj:87 cheshire.core/parse-string
RestFn.java:423 clojure.lang.RestFn.invoke
json.clj:12 ring.middleware.json/read-json
RestFn.java:423 clojure.lang.RestFn.invoke
json.clj:19 ring.middleware.json/wrap-json-body[fn]
json.clj:42 ring.middleware.json/wrap-json-response[fn]
Var.java:415 clojure.lang.Var.invoke
reload.clj:18 ring.middleware.reload/wrap-reload[fn]
stacktrace.clj:15 ring.middleware.stacktrace/wrap-stacktrace-log[fn]
stacktrace.clj:79 ring.middleware.stacktrace/wrap-stacktrace-web[fn]
jetty.clj:18 ring.adapter.jetty/proxy-handler[fn]
(Unknown Source) ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$0.handle
HandlerWrapper.java:111 org.eclipse.jetty.server.handler.HandlerWrapper.handle
Server.java:349 org.eclipse.jetty.server.Server.handle
AbstractHttpConnection.java:452 org.eclipse.jetty.server.AbstractHttpConnection.handleRequest
AbstractHttpConnection.java:894 org.eclipse.jetty.server.AbstractHttpConnection.content
AbstractHttpConnection.java:948 org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content
HttpParser.java:857 org.eclipse.jetty.http.HttpParser.parseNext
HttpParser.java:235 org.eclipse.jetty.http.HttpParser.parseAvailable
AsyncHttpConnection.java:76 org.eclipse.jetty.server.AsyncHttpConnection.handle
SelectChannelEndPoint.java:609 org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle
SelectChannelEndPoint.java:45 org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run
QueuedThreadPool.java:599 org.eclipse.jetty.util.thread.QueuedThreadPool.runJob
QueuedThreadPool.java:534 org.eclipse.jetty.util.thread.QueuedThreadPool$3.run
Thread.java:680 java.lang.Thread.run
In an ideal world, I'd prefer to be able to specify a function/handler to call when malformed JSON is present in the request body so I can specify what the response should look like. Unfortunately, I'm new to Clojure and Ring so I'm not entirely sure where a logical place to specify that handler would be if that functionality were to be added.
Currently there is no way to access the original body of the request when using the middleware since the middleware reads and InputStream and there's no way to reset its position to 0.
I'd suggest at least assoc-ing the body string from here: https://github.com/ring-clojure/ring-json/blob/master/src/ring/middleware/json.clj#L14 to the request map for future reference.
Add support for a :key-fn to the wrap-json-body middleware which is passed to cheshire to convert keys.
I may have missed it, but is there support for pretty-printing JSON responses?
I'm looking for something like python's json indent option:
python
Python 2.7.9 (default, Mar 1 2015, 12:57:24)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import json
>>> json.dump({"a" : 1, "b" : 2}, sys.stdout)
{"a": 1, "b": 2}>>>
>>> json.dump({"a" : 1, "b" : 2}, sys.stdout, indent = 2)
{
"a": 1,
"b": 2
}>>>
Looking at the code I noticed this: https://github.com/ring-clojure/ring-json/blob/master/src/ring/middleware/json.clj#L40
Shouldn't the binding of big-decimals be scoped to the parsing of the JSON, and not to chaining to other handlers?
slurp
can have quite detrimental effects on performance. This example is with jsonista but since both it and cheshire use jackson I expect about the same order of magnitude of effect:
(require '[criterium.core :as cc]
'[jsonista.core :as json])
(def m {:a 1 :b 2 :c "3" :d ["5"]})
(def mapper (json/object-mapper {:decode-key-fn true}))
(def bs (json/write-value-as-bytes m))
(type bs) ;; => [B
(defn bytes->str [^"[B" bs] (String. bs))
(bytes->str bs) ;; => "{\"a\":1,\"b\":2,\"c\":\"3\",\"d\":[\"5\"]}"
(cc/bench (json/read-value (slurp bs) mapper))
;;; Execution time mean : 8.653311 µs
(cc/bench (json/read-value (bytes->str bs) mapper))
;;; Execution time mean : 2.068923 µs
(cc/bench (json/read-value bs mapper))
;;; Execution time mean : 1.912441 µs
I don't mind submitting a PR with the fix.
Hi team 👋🏽
I have been using ring-json
in a few of my projects, and have been wondering if it makes sense to return the default malformed response as a JSON response, instead of text in the body. I believe it is useful since most api services expect a JSON response that they try to unmarshall and may fail when making a malformed request. But this is my opinion and may not be true about other projects in the wild.
If you agree with this, I am happy to create a pull request and make the change. I currently override it by providing my own, but was wondering if more people would find it useful.
Looking forward to hearing how you feel about it. Also, I think it's an awesome library regardless of this change 🙏🏽
There are a couple of Cheshire supported options that the middleware does not pass through. We could add either support for key-fn explicitly or have a map that is passed through to Cheshire.
We need at least the :key-fn option so that the namespace qualified keys can be unqualified before exposing them outside of our system. If there's any interest in this, I'd be happy to raise a PR.
Thanks
I've just tried to add [ring/ring-json "0.2.0"] as dependency in my project and it brings the following error:
vbauer@vladislav-bauer:~/workspace/clojure/testproject$ lein ring server
Exception in thread "main" java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:270)
at clojure.lang.RT.loadClassForName(RT.java:2098)
at clojure.lang.RT.load(RT.java:430)
at clojure.lang.RT.load(RT.java:411)
at clojure.core$load$fn__5018.invoke(core.clj:5530)
at clojure.core$load.doInvoke(core.clj:5529)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5336)
at clojure.core$load_lib$fn__4967.invoke(core.clj:5375)
at clojure.core$load_lib.doInvoke(core.clj:5374)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$load_libs.doInvoke(core.clj:5417)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:621)
at clojure.core$use.doInvoke(core.clj:5507)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at compojure.handler$loading__4910__auto__.invoke(handler.clj:1)
at compojure.handler__init.load(Unknown Source)
at compojure.handler__init.<clinit>(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:270)
at clojure.lang.RT.loadClassForName(RT.java:2098)
at clojure.lang.RT.load(RT.java:430)
at clojure.lang.RT.load(RT.java:411)
at clojure.core$load$fn__5018.invoke(core.clj:5530)
at clojure.core$load.doInvoke(core.clj:5529)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5336)
at clojure.core$load_lib$fn__4967.invoke(core.clj:5375)
at clojure.core$load_lib.doInvoke(core.clj:5374)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$load_libs.doInvoke(core.clj:5413)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:621)
at clojure.core$use.doInvoke(core.clj:5507)
at clojure.lang.RestFn.invoke(RestFn.java:930)
at noir.util.middleware$loading__4910__auto__.invoke(middleware.clj:1)
at noir.util.middleware__init.load(Unknown Source)
at noir.util.middleware__init.<clinit>(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:270)
at clojure.lang.RT.loadClassForName(RT.java:2098)
at clojure.lang.RT.load(RT.java:430)
at clojure.lang.RT.load(RT.java:411)
at clojure.core$load$fn__5018.invoke(core.clj:5530)
at clojure.core$load.doInvoke(core.clj:5529)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5336)
at clojure.core$load_lib$fn__4967.invoke(core.clj:5375)
at clojure.core$load_lib.doInvoke(core.clj:5374)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$load_libs.doInvoke(core.clj:5413)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$require.doInvoke(core.clj:5496)
at clojure.lang.RestFn.invoke(RestFn.java:619)
at testproject.handler$eval9$loading__4910__auto____10.invoke(handler.clj:1)
at testproject.handler$eval9.invoke(handler.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6619)
at clojure.lang.Compiler.eval(Compiler.java:6608)
at clojure.lang.Compiler.load(Compiler.java:7064)
at clojure.lang.RT.loadResourceScript(RT.java:370)
at clojure.lang.RT.loadResourceScript(RT.java:361)
at clojure.lang.RT.load(RT.java:440)
at clojure.lang.RT.load(RT.java:411)
at clojure.core$load$fn__5018.invoke(core.clj:5530)
at clojure.core$load.doInvoke(core.clj:5529)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.core$load_one.invoke(core.clj:5336)
at clojure.core$load_lib$fn__4967.invoke(core.clj:5375)
at clojure.core$load_lib.doInvoke(core.clj:5374)
at clojure.lang.RestFn.applyTo(RestFn.java:142)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$load_libs.doInvoke(core.clj:5413)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.core$apply.invoke(core.clj:619)
at clojure.core$require.doInvoke(core.clj:5496)
at clojure.lang.RestFn.invoke(RestFn.java:457)
at user$eval5.invoke(form-init234056340182660043.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6619)
at clojure.lang.Compiler.eval(Compiler.java:6608)
at clojure.lang.Compiler.load(Compiler.java:7064)
at clojure.lang.Compiler.loadFile(Compiler.java:7020)
at clojure.main$load_script.invoke(main.clj:294)
at clojure.main$init_opt.invoke(main.clj:299)
at clojure.main$initialize.invoke(main.clj:327)
at clojure.main$null_opt.invoke(main.clj:362)
at clojure.main$main.doInvoke(main.clj:440)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:419)
at clojure.lang.AFn.applyToHelper(AFn.java:163)
at clojure.lang.Var.applyTo(Var.java:532)
at clojure.main.main(main.java:37)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.fileupload.UploadContext
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:190)
at ring.middleware.multipart_params__init.__init0(Unknown Source)
at ring.middleware.multipart_params__init.<clinit>(Unknown Source)
... 97 more
project.clj:
(defproject
testproject
"0.1.0-SNAPSHOT"
:repl-options {:init-ns testproject.repl}
:dependencies
[[com.h2database/h2 "1.3.175"]
[ring-server "0.3.1"]
[ring/ring-json "0.2.0"]
[environ "0.4.0"]
[com.taoensso/timbre "2.7.1"]
[korma "0.3.0-RC6"]
[http-kit "2.1.16"]
[com.taoensso/tower "2.0.1"]
[org.clojure/clojure "1.5.1"]
[org.clojure/clojure-contrib "1.2.0"]
[log4j "1.2.17"
:exclusions
[javax.mail/mail javax.jms/jms com.sun.jdmk/jmxtools com.sun.jmx/jmxri]]
[compojure "1.1.6"]
[lib-noir "0.7.9"]
[com.postspectacular/rotor "0.1.0"]]
:ring {:handler testproject.handler/app
:init testproject.handler/init
:destroy testproject.handler/destroy
:port 8080}
:profiles {:uberjar {:aot :all}
:production {:ring {:open-browser? false
:stacktraces? false
:auto-reload? false}}
:dev {:dependencies [[ring-mock "0.1.5"] [ring/ring-devel "1.2.1"]],
:env {:selmer-dev true}}}
:url "http://example.com/FIXME"
:main testproject.core
:plugins [[lein-ring "0.8.10"] [lein-environ "0.4.0"]]
:description "FIXME: write description"
:min-lein-version "2.0.0")
It looks like Apache FileUpload is missed, but I don't use it.
Could you help me with it, please?
PS: I used https://github.com/yogthos/luminus-template to create project.
I'm using ring-json to deliver json data to a front end that uses reagent to render some d3 charts. I've had the simple project working locally, but when I deployed it to heroku I got the following errors (from the heroku log):
2016-08-01T15:50:38.955857+00:00 app[web.1]: java.lang.Exception: Unrecognized body: [{:key "GB", :values [{:y 2.4555984, :x 2002} {:y 2.519768, :x 2004} {:y 2.4532163, :x 2006} {:y 2.420068, :x 2008} {:y 2.464492, :x 2010} {:y 2.321085, :x 2012}]} {:key "ES", :values [{:y 2.2434933, :x 2002} {:y 2.34095, :x 2004} {:y 2.1764393, :x 2006} {:y 2.0458074, :x 2008} {:y 2.1055703, :x 2010} {:y 2.041821, :x 2012}]} {:key "DE", :values [{:y 2.3088598, :x 2002} {:y 2.3240418, :x 2004} {:y 2.414952, :x 2006} {:y 2.2453654, :x 2008} {:y 2.2269878, :x 2010} {:y 2.1301556, :x 2012}]} {:key "FR", :values [{:y 2.292432, :x 2002} {:y 2.6937985, :x 2004} {:y 2.2779455, :x 2006} {:y 2.3077664, :x 2008} {:y 2.390625, :x 2010} {:y 2.3109756, :x 2012}]} {:key "HU", :values [{:y 2.5220544, :x 2002} {:y 2.570761, :x 2004} {:y 2.7397892, :x 2006} {:y 3.0420985, :x 2008} {:y 2.8456118, :x 2010} {:y 2.5978153, :x 2012}]} {:key "FI", :values [{:y 2.3738055, :x 2002} {:y 2.4264107, :x 2004} {:y 3.1687763, :x 2006} {:y 3.2200456, :x 2008} {:y 3.2385516, :x 2010} {:y 2.240783, :x 2012}]} {:key "PT", :values [{:y 2.8570483, :x 2002} {:y 2.8615985, :x 2004} {:y 2.649865, :x 2006} {:y 2.7748206, :x 2008} {:y 2.8316278, :x 2010} {:y 2.8707578, :x 2012}]} {:key "SE", :values [{:y 2.7565827, :x 2002} {:y 2.7382352, :x 2004} {:y 3.7057602, :x 2006} {:y 3.5786886, :x 2008} {:y 2.478958, :x 2010} {:y 2.2799134, :x 2012}]}]
2016-08-01T15:50:38.955860+00:00 app[web.1]: at ring.util.servlet$update_servlet_response.invokeStatic(servlet.clj:115)
2016-08-01T15:50:38.955859+00:00 app[web.1]: at ring.util.servlet$set_body.invoke(servlet.clj:84)
2016-08-01T15:50:38.955861+00:00 app[web.1]: at ring.adapter.jetty$proxy_handler$fn__3274.invoke(jetty.clj:26)
2016-08-01T15:50:38.955861+00:00 app[web.1]: at ring.util.servlet$update_servlet_response.invoke(servlet.clj:107)
2016-08-01T15:50:38.955863+00:00 app[web.1]: at ring.adapter.jetty.proxy$org.eclipse.jetty.server.handler.AbstractHandler$ff19274a.handle(Unknown Source)
2016-08-01T15:50:38.955865+00:00 app[web.1]: at org.eclipse.jetty.server.Server.handle(Server.java:497)
2016-08-01T15:50:38.955858+00:00 app[web.1]: at ring.util.servlet$set_body.invokeStatic(servlet.clj:105)
2016-08-01T15:50:38.955864+00:00 app[web.1]: at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
2016-08-01T15:50:38.955867+00:00 app[web.1]: at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
2016-08-01T15:50:38.955869+00:00 app[web.1]: at java.lang.Thread.run(Thread.java:745)
2016-08-01T15:50:38.955866+00:00 app[web.1]: at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:540)
2016-08-01T15:50:38.955868+00:00 app[web.1]: at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
2016-08-01T15:50:38.955866+00:00 app[web.1]: at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257)
2016-08-01T15:50:38.955865+00:00 app[web.1]: at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:310)
I'm not sure where to begin with this. Nor am I certain that it is a problem with ring-json. Do I perhaps need to set the headers somewhere? Any help would be greatly appreciated. Temporarily, here is a link to the project running on heroku: https://warm-dusk-72249.herokuapp.com/ . The project itself can be found at http://github.com/ezmiller/esd-viz.
I might be missing something but with wrap-json-body {keywords? true}
I'm getting an HttpInputStream rather than a map.
Not sure what I'm doing wrong here.
As ring-json user I want cheshire version upgraded to 5.12.0 so that i do not have vulnerabilities in dependencies.
The root cause lies in jackson-dataformat-cbor/2.5.2 dependency which relates to multiple known CVE reports. See vulnerabilities list on maven page.
chechire 5.12.0 has the latest jackson-dataformat dependecies without known vulnerabilities as of now
Retrieving cheshire/cheshire/5.12.0/cheshire-5.12.0.jar from clojars
[cheshire "5.12.0"]
[com.fasterxml.jackson.core/jackson-core "2.15.2"]
[com.fasterxml.jackson.dataformat/jackson-dataformat-cbor "2.15.2" :exclusions [[com.fasterxml.jackson.core/jackson-databind]]]
[com.fasterxml.jackson.dataformat/jackson-dataformat-smile "2.15.2" :exclusions [[com.fasterxml.jackson.core/jackson-databind]]]
[tigris "0.1.2"]
jackson-dataformat-cbor/2.15.2
jackson-dataformat-smile/2.15.2
;;cheshire stuff
[cheshire.core :refer :all]
[cheshire.generate :refer [add-encoder encode-str remove-encoder]]))
;; There are also helpers for common encoding actions:
(add-encoder java.net.URI encode-str)
with the wrap-json-response
functions i get these java.lang.Exception: Don't know how to write JSON of class java.net.URI
when i use [cheshire 5.1.1]
and use their (generate-string)
i get no stacktraces
By default the cheshire json parser converts floats to Doubles on parsing - this is dangerous as Doubles are imprecise - especially for monetary values.
It would be great if wrap-json-params and wrap-json-body could be configured to set the use-bigdecimals? binding to true on request.
for others who meet this, we made a workaround by writing our own wrapper:
(defn wrap-json-body-bigdecimal
"delegates to wrap-json-body with bigdecimal parsing turned on"
[handler & opts]
(fn [request]
(binding [parse/*use-bigdecimals?* true]
((apply json/wrap-json-body handler opts) request))))
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.