(text json)

Reference

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

Functions

Values

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