Overview
JSON, read into a tree: RFC 8259, one character at a time.
(import (text json))
(match (parse-json "{\"name\": \"http\", \"tags\": [\"net\", \"web\"]}")
((Ok (JsonObj m)) (map-try-ref m "name")) ; (Some (JsonStr "http"))
((Ok other) None)
((Err why) (println why) None))
A document is read into a Json, a union with a case for each
kind of JSON value. Reading a record straight from JSON, and writing one
as JSON, is (text json-codec)’s: its def/json-type declares
a record and the instances that convert it.
What is read. Exactly RFC 8259: one value, with whitespace
around it and nothing else after it. A byte order mark before the value is
skipped. There are no comments, no trailing commas, no single quotes and
no unquoted keys. A number may not have a leading zero, and needs digits
after its decimal point and its exponent. A control character in a string
has to be escaped, and a surrogate has to be one half of a pair, written
out or as two \u escapes; a pair is read as one character.
Numbers. A number without a fraction or an exponent is a
JsonInt, a long. One with either, or one too wide for a
long, is a JsonFloat. So 1 and 1.0 are
different values in the tree; (text json-codec) reads either into
a double, and only the first into an integer.
Objects. An object is a (Map string Json), so the order
its keys were written in is not kept, and when a key is written twice the
last value wins.
Errors. A document that is not JSON is an Err saying
where and why: line 1, column 7: ']' does not begin a value.
Nothing is raised. A document nested deeper than
json-max-depth is refused the same way rather than exhausting the
stack.
Not here yet. There is no writer: a Json cannot yet be
turned back into text by this module.
See also: Json, parse-json, read-json
Reference
Types
Json
union
A JSON value.
JsonNull- null.
JsonBool- true or false.
JsonInt- A number with no fraction and no exponent that fits in a long.
JsonFloat- Any other number.
JsonStr- A string, its escapes resolved.
JsonArr- An array, in order.
JsonObj- An object, by key. The order of the keys is not kept; a key written twice keeps its last value.
See also: parse-json
Functions
read-json
function
(: read-json (-> TextInputPort (Result string Json)))
(read-json port)
Reads one JSON document from a port.
port- The port. Everything left in it is read: one value, and only space after it.
- returns
- The value, or why the text is not JSON, with its line and column.
A byte order mark before the value is skipped and does not count as a column. On a bjoroutine the port is read without blocking the thread.
See also: parse-json
parse-json
function
(: parse-json (-> string (Result string Json)))
(parse-json text)
Reads one JSON document from a string.
text- The document.
- returns
- The value, or why the text is not JSON, with its line and column.
(parse-json "[1, 2.5, null]") ; (Ok (JsonArr [(JsonInt 1) (JsonFloat 2.5) JsonNull]))
(parse-json "[1, 2,]") ; (Err "line 1, column 7: ']' does not begin a value")
See also: read-json
Values
json-max-depth
value
(: json-max-depth int)
How deep arrays and objects may nest before reading refuses the document: 1000.
See also: read-json