Read JSON into plain Clojure data, built on the Java library io.github.ralfspoeth/greyson.
Reading is a two-step process:
read-json / read-json-str parse text into Greyson's
immutable JsonValue tree.->clj converts that tree into maps, vectors, strings,
BigDecimals, booleans and nil.Writing mirrors this: ->greyson turns Clojure data into a
Greyson JsonValue, and write-json / write-json-str turn
Clojure data or a JsonValue into JSON text.
Example:
(->clj (read-json-str "{"a": [1, true, null]}")) ;; => {"a" [1M true nil]}
Read JSON into plain Clojure data, built on the Java library
io.github.ralfspoeth/greyson.
Reading is a two-step process:
1. `read-json` / `read-json-str` parse text into Greyson's
immutable `JsonValue` tree.
2. `->clj` converts that tree into maps, vectors, strings,
BigDecimals, booleans and nil.
Writing mirrors this: `->greyson` turns Clojure data into a
Greyson `JsonValue`, and `write-json` / `write-json-str` turn
Clojure data or a `JsonValue` into JSON text.
Example:
(->clj (read-json-str "{\"a\": [1, true, null]}"))
;; => {"a" [1M true nil]}(->clj v)(->clj v key-fn)Converts the Greyson JsonValue v into plain Clojure data:
JSON object -> persistent map JSON array -> vector JSON string -> String JSON number -> BigDecimal (full precision, e.g. 1M, 0.1M) true / false -> Boolean null -> nil
key-fn is applied to every object member name (a String) to
produce the map key, at every level of nesting. It defaults to
identity, so keys stay strings. Common choices:
(->clj v) ;; {"a" 1M} (->clj v keyword) ;; {:a 1M} (->clj v #(keyword "my.ns" %)) ;; {:my.ns/a 1M}
If an object has duplicate member names, the last one wins (this
is Greyson's behaviour). If key-fn maps two different names to
the same key, the later member in iteration order wins, and that
order is unspecified.
Throws IllegalArgumentException if v is not a JsonValue.
Converts the Greyson `JsonValue` `v` into plain Clojure data:
JSON object -> persistent map
JSON array -> vector
JSON string -> String
JSON number -> BigDecimal (full precision, e.g. 1M, 0.1M)
true / false -> Boolean
null -> nil
`key-fn` is applied to every object member name (a String) to
produce the map key, at every level of nesting. It defaults to
`identity`, so keys stay strings. Common choices:
(->clj v) ;; {"a" 1M}
(->clj v keyword) ;; {:a 1M}
(->clj v #(keyword "my.ns" %)) ;; {:my.ns/a 1M}
If an object has duplicate member names, the last one wins (this
is Greyson's behaviour). If `key-fn` maps two different names to
the same key, the later member in iteration order wins, and that
order is unspecified.
Throws `IllegalArgumentException` if `v` is not a `JsonValue`.(->greyson x)(->greyson x key-fn)Converts Clojure data x into a Greyson JsonValue:
nil -> JsonNull String -> JsonString true / false -> JsonBoolean keyword -> JsonString without the colon, namespace kept (:a/b -> "a/b") symbol, char -> JsonString integer, BigInt, BigDecimal, double, float -> JsonNumber (exact for integers, BigInts and BigDecimals) ratio -> JsonNumber via double map (incl. records) -> JsonObject vector, list, seq, set, any Iterable, Java array -> JsonArray (sets in iteration order) JsonValue -> returned as is
key-fn turns every map key into a member name and must return a
String. The default keeps strings, drops the colon from keywords
but keeps their namespace, and applies str to anything else:
(->greyson {:a 1}) ;; {"a": 1} (->greyson {:my.ns/a 1}) ;; {"my.ns/a": 1} (->greyson {:my.ns/a 1} name) ;; {"a": 1}
If two keys map to the same name, one of them wins; which one is unspecified.
Throws IllegalArgumentException for values of any other type and
when key-fn returns a non-String, and NumberFormatException for
NaN and infinite doubles. Lazy sequences are realised, so infinite
ones never return.
Converts Clojure data `x` into a Greyson `JsonValue`:
nil -> JsonNull
String -> JsonString
true / false -> JsonBoolean
keyword -> JsonString without the colon,
namespace kept (:a/b -> "a/b")
symbol, char -> JsonString
integer, BigInt, BigDecimal,
double, float -> JsonNumber (exact for integers,
BigInts and BigDecimals)
ratio -> JsonNumber via double
map (incl. records) -> JsonObject
vector, list, seq, set,
any Iterable, Java array -> JsonArray (sets in iteration order)
JsonValue -> returned as is
`key-fn` turns every map key into a member name and must return a
String. The default keeps strings, drops the colon from keywords
but keeps their namespace, and applies `str` to anything else:
(->greyson {:a 1}) ;; {"a": 1}
(->greyson {:my.ns/a 1}) ;; {"my.ns/a": 1}
(->greyson {:my.ns/a 1} name) ;; {"a": 1}
If two keys map to the same name, one of them wins; which one is
unspecified.
Throws `IllegalArgumentException` for values of any other type and
when `key-fn` returns a non-String, and `NumberFormatException` for
NaN and infinite doubles. Lazy sequences are realised, so infinite
ones never return.(read-json rdr)Reads exactly one JSON value from rdr and returns it as a
Greyson JsonValue. Closes rdr when done.
Any JSON value is accepted at the top level, including scalars
such as 42 or "text". Surrounding whitespace is ignored.
Throws:
java.util.NoSuchElementException if the input is empty or
contains only whitespace,io.github.ralfspoeth.json.io.JsonParseException if the input
is malformed or has anything after the first value,java.io.IOException if reading from rdr fails.Reads exactly one JSON value from `rdr` and returns it as a
Greyson `JsonValue`. Closes `rdr` when done.
Any JSON value is accepted at the top level, including scalars
such as `42` or `"text"`. Surrounding whitespace is ignored.
Throws:
- `java.util.NoSuchElementException` if the input is empty or
contains only whitespace,
- `io.github.ralfspoeth.json.io.JsonParseException` if the input
is malformed or has anything after the first value,
- `java.io.IOException` if reading from `rdr` fails.(read-json-str s)Reads exactly one JSON value from the string s and returns it
as a Greyson JsonValue. Throws the same exceptions as
read-json.
Reads exactly one JSON value from the string `s` and returns it as a Greyson `JsonValue`. Throws the same exceptions as `read-json`.
(write-json w x)(write-json w x {:keys [key-fn pretty] :or {key-fn impl/json-key}})Writes x as JSON text to w, then flushes w. Does not close
w, so several values can be written to the same stream; use
with-open to close it. Returns nil.
x is Clojure data or a Greyson JsonValue; Clojure data is
converted with ->greyson. Options:
:key-fn turns map keys into member names, as for ->greyson
(default: strings as is, keywords without the colon)
:pretty if true, indent with four spaces per level and put each
member and array element on its own line; empty objects
and arrays stay {} and []. Default: compact, on a
single line.
Member order in objects is not guaranteed. Throws the same
exceptions as ->greyson, and IOException if writing fails.
Writes `x` as JSON text to `w`, then flushes `w`. Does not close
`w`, so several values can be written to the same stream; use
`with-open` to close it. Returns nil.
`x` is Clojure data or a Greyson `JsonValue`; Clojure data is
converted with `->greyson`. Options:
:key-fn turns map keys into member names, as for `->greyson`
(default: strings as is, keywords without the colon)
:pretty if true, indent with four spaces per level and put each
member and array element on its own line; empty objects
and arrays stay `{}` and `[]`. Default: compact, on a
single line.
Member order in objects is not guaranteed. Throws the same
exceptions as `->greyson`, and `IOException` if writing fails.(write-json-str x)(write-json-str x opts)Returns x as a JSON string. Takes the same options as
write-json and produces the same text.
(write-json-str {:a [1 nil]}) ;; => "{"a": [1, null]}"
(write-json-str {:a [1 nil]} {:pretty true}) ;; => { ;; "a": [ ;; 1, ;; null ;; ] ;; }
Returns `x` as a JSON string. Takes the same options as
`write-json` and produces the same text.
(write-json-str {:a [1 nil]})
;; => "{\"a\": [1, null]}"
(write-json-str {:a [1 nil]} {:pretty true})
;; => {
;; "a": [
;; 1,
;; null
;; ]
;; }cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |