# gizlang:json

JSON (RFC 8259) as a value, read with parse and written with stringify as JavaScript's JSON.stringify writes it. Objects keep their keys in order; a repeated key keeps the last value, as JSON.parse.

```gizlang
import * as Json from "gizlang:json";
```

## Types

### `Json`

```gizlang
type Json = | { kind: "null"; } | { kind: "boolean"; value: bool; } | { kind: "number"; value: f64; } | { kind: "string"; value: string; } | { kind: "array"; items: Vec<Json>; } | { kind: "object"; keys: Vec<string>; values: Vec<Json>; }
```

A JSON value: null, boolean, number, string, array or object.

- `null`
- `boolean`
- `number`
- `string`
- `array`
- `object`

### `JsonError`

```gizlang
type JsonError = { offset: i64; message: string; }
```

Where the text stops being JSON, in bytes.

- `offset`: `i64`
- `message`: `string`

### `JsonReader`

```gizlang
type JsonReader
```

A reader that walks JSON text without building a tree.

Opaque: create and use it through this module's functions.

### `JsonSpan`

```gizlang
type JsonSpan = { start: i64; end: i64; }
```

Half-open UTF-8 byte offsets into the retained input, excluding surrounding whitespace.

- `start`: `i64`
- `end`: `i64`

## Functions

### `parse`

```gizlang
function parse(text: string): Json throws JsonError
```

The JSON value of TEXT. It fails at the first error, with its offset.

Effects: fail.

### `parseUnique`

```gizlang
function parseUnique(text: string): Json throws JsonError
```

The same JSON parser, rejecting repeated decoded keys in every object.
Use for manifests and authenticated contracts with one meaning per field.

Effects: fail.

### `parseBytes`

```gizlang
function parseBytes(data: bytes): Json throws JsonError
```

parse of JSON text in UTF-8 bytes; bytes that are not UTF-8 are an error at offset 0.

Effects: fail.

### `ofInteger`

```gizlang
function ofInteger(n: i64): Json
```

The number N.

### `strings`

```gizlang
function strings(values: Vec<string>): Json
```

A JSON array of the strings VALUES.

Effects: fail.

### `rpcResult`

```gizlang
function rpcResult(id: Json, result: Json): Json
```

The answer RESULT to the request ID.

Effects: fail.

### `rpcError`

```gizlang
function rpcError(id: Json, code: i64, message: string): Json
```

The error answer to the request ID (Json.null() when the request has no readable id).

Effects: fail.

### `rpcCall`

```gizlang
function rpcCall(id: Json, method: string, params: Json): Json
```

The request ID that calls METHOD with PARAMS.

Effects: fail.

### `rpcNotice`

```gizlang
function rpcNotice(method: string, params: Json): Json
```

A notification of METHOD: a request without an id, which gets no answer.

Effects: fail.

### `stringify`

```gizlang
function stringify(value: Json): string
```

As JSON.stringify: no spaces, a number as String(n) (NaN and Infinity as null),
and a string with ", \ and control characters escaped.

Effects: fail.

### `stringifyIndented`

```gizlang
function stringifyIndented(value: Json, indent: i64): string
```

As JSON.stringify(value, null, indent): each item and key on its own line,
indented `indent` spaces a level, "key": value; empty arrays and objects
stay [] and {}.

Effects: fail.

### `stringifySpaced`

```gizlang
function stringifySpaced(value: Json): string
```

As Python's json.dumps (and the tojson of Jinja chat templates): one line, ", " between items and ": " after a key.

Effects: fail.

### `quote`

```gizlang
function quote(text: string): string
```

TEXT as a JSON string literal, quoted and escaped.

Effects: fail.

### `writeString`

```gizlang
function writeString(out: mut bytes, text: string): void
```

text as a JSON string, appended to out, for writing a typed value field by
field (its keys and strings). A text with nothing to escape, nearly every
one, is one scan and one copy.

Effects: fail.

### `integerDigits`

```gizlang
function integerDigits(n: i64): i64
```

The count of N's decimal digits, without its sign.

Effects: fail.

### `writeInteger`

```gizlang
function writeInteger(out: mut bytes, n: i64): void
```

Appends N's decimal digits: their room first, then the digits from the right, so none is moved twice.

Effects: fail.

### `withInteger`

```gizlang
function withInteger(prefix: bytes, n: i64): bytes
```

PREFIX followed by N's decimal digits, made in one allocation: JavaScript's `"k" + i`, where appending to a copy
of the prefix regrew it digit by digit: writeInteger was 15% of a Map benchmark.

Effects: fail.

### `writeExactInteger`

```gizlang
function writeExactInteger(out: mut bytes, n: i64): void
```

n as a JSON number when a double holds it exactly (|n| <= 2^53 - 1, so
JavaScript reads the same value), else as a string of its digits.

Effects: fail.

### `writeNumber`

```gizlang
function writeNumber(out: mut bytes, n: f64): void
```

Writes N as a JSON number, the shortest text that reads back to N; null when N is not finite.

Effects: fail.

### `reader`

```gizlang
function reader(text: string): JsonReader
```

A reader that walks TEXT one value at a time, without building a tree.

Effects: fail.

### `encode`

```gizlang
function encode<T>(value: T): string
```

VALUE as JSON text, as JSON.stringify writes it: a record is an object of its fields in order (an undefined field is
left out), a union's case also has its `kind`, a Vec is an array, a Map<string, V> an object, undefined is null.

### `encodeIndented`

```gizlang
function encodeIndented<T>(value: T, indent: i64): string throws JsonError
```

encode, then laid out as JSON.stringify(value, null, indent) lays it out.

### `decode`

```gizlang
function decode<T>(text: string): T throws JsonError
```

TEXT as a T, as encode writes one; a field the object lacks is an error unless its type takes undefined, and a field
the type lacks is skipped.

### `open`

```gizlang
function open(out: mut bytes): void
```

`{`, before the fields.

Effects: fail.

### `close`

```gizlang
function close(out: mut bytes): void
```

`}`, after the fields.

Effects: fail.

### `fieldName`

```gizlang
function fieldName(out: mut bytes, name: string): void
```

`"NAME":`, after a comma unless it is the first field.

Effects: fail.

### `field`

```gizlang
function field<T>(out: mut bytes, name: string, value: T): void
```

The field NAME of VALUE.

### `optionalField`

```gizlang
function optionalField<T>(out: mut bytes, name: string, value: Option<T>): void
```

The field NAME of VALUE, left out when it is undefined, as JSON.stringify leaves it out.

### `kindField`

```gizlang
function kindField(out: mut bytes, name: string): void
```

A union case's `"kind":"NAME"`.

Effects: fail.

### `writeValue`

```gizlang
function writeValue<T>(out: mut bytes, value: T): void
```

VALUE as itself: the case of an untagged union.

### `expectObject`

```gizlang
function expectObject(json: Json): void throws JsonError
```

An error unless JSON is an object.

### `memberOf`

```gizlang
function memberOf(json: Json, name: string): Json
```

The field NAME of the object JSON, or null when it has none.

Effects: fail.

### `kindOf`

```gizlang
function kindOf(json: Json): string throws JsonError
```

The `kind` of the object JSON: the case of a union.

Effects: fail.

### `typeofJson`

```gizlang
function typeofJson(json: Json): string
```

What TypeScript's `typeof` says of JSON's value: the case of an untagged union it is.

### `unknownKind`

```gizlang
function unknownKind(kind: string): void throws JsonError
```

The error of a union that has no case KIND.

Effects: fail.

## Methods

### `Json.get`

```gizlang
function Json.get(self: Json, key: string): Option<Json>
```

The value under `key` of an object; none for a missing key or another kind.

Effects: fail.

### `Json.field`

```gizlang
function Json.field(self: Json, key: string): Json
```

The value under `key` of an object, else null, so a nested read chains:
`event.field("usage").field("total_tokens").integer()`.

Effects: fail.

### `Json.isObject`

```gizlang
function Json.isObject(self: Json): bool
```

Whether this is an object.

### `Json.exactFields`

```gizlang
function Json.exactFields(self: Json, names: Vec<string>): bool
```

Exact decoded object fields, without allocating a map or parsing again.
Wire schemas still use parseUnique to reject duplicate decoded JSON keys.

Effects: fail.

### `Json.text`

```gizlang
function Json.text(self: Json): string
```

A string's text; "" for another kind.

### `Json.boolean`

```gizlang
function Json.boolean(self: Json): bool
```

A boolean's value; false for another kind.

### `Json.list`

```gizlang
function Json.list(self: Json): Vec<Json>
```

An array's items; none for another kind.

### `Json.keys`

```gizlang
function Json.keys(self: Json): Vec<string>
```

An object's keys, in order; none for another kind.

### `Json.values`

```gizlang
function Json.values(self: Json): Vec<Json>
```

An object's values, in key order; none for another kind.

### `Json.integer`

```gizlang
function Json.integer(self: Json): i64
```

A number toward zero as an integer; 0 for another kind or one past i64's
exact range (2^53).

Effects: fail.

### `Json.booleanOr`

```gizlang
function Json.booleanOr(self: Json, otherwise: bool): bool
```

A boolean's value; OTHERWISE for another kind: `config.field("lowercase").booleanOr(true)`.

### `Json.numberOr`

```gizlang
function Json.numberOr(self: Json, otherwise: f64): f64
```

A number's value; OTHERWISE for another kind: `config.field("eps").numberOr(1.0e-5)`.

### `Json.integerOr`

```gizlang
function Json.integerOr(self: Json, otherwise: i64): i64
```

A number toward zero as an integer; OTHERWISE for another kind: `config.field("hidden_size").integerOr(768)`.

Effects: fail.

### `JsonReader.error`

```gizlang
function JsonReader.error(self: JsonReader): Option<JsonError>
```

The first error of the reader, or none.

### `JsonReader.object`

```gizlang
function JsonReader.object(self: mut JsonReader): bool
```

Enters the object at the reader; false (and an error) when the next value is not an object.

Effects: fail.

### `JsonReader.array`

```gizlang
function JsonReader.array(self: mut JsonReader): bool
```

Enters the array at the reader; false (and an error) when the next value is not an array.

Effects: fail.

### `JsonReader.skip`

```gizlang
function JsonReader.skip(self: mut JsonReader): void
```

Skips the next value, with all that it holds.

Effects: fail.

### `JsonReader.span`

```gizlang
function JsonReader.span(self: mut JsonReader): Option<JsonSpan>
```

Validate and consume one value without building its tree or decoding strings.
A later typed reader may decode input.slice(span.start, span.end); errors publish no span.

Effects: fail.

### `JsonReader.key`

```gizlang
function JsonReader.key(self: mut JsonReader): bool
```

Moves to the next key of the object; false at its end.

Effects: fail.

### `JsonReader.keyIs`

```gizlang
function JsonReader.keyIs(self: JsonReader, key: string): bool
```

Whether the current key is KEY.

Effects: fail.

### `JsonReader.keyText`

```gizlang
function JsonReader.keyText(self: JsonReader): Option<string>
```

Decode the current validated object key without consuming its value or
changing the reader. Empty keys are some(""); no current key or a stopped
reader is none. The ordinary string decoder owns all escape semantics.

Effects: fail.

### `JsonReader.item`

```gizlang
function JsonReader.item(self: mut JsonReader): bool
```

Moves to the next item of the array; false at its end.

Effects: fail.

### `JsonReader.fail`

```gizlang
function JsonReader.fail(self: mut JsonReader, message: string): void
```

A decoder's own error (a missing field, a value out of range): it stops the
reader like a syntax error, and the first error is the one kept.

### `JsonReader.number`

```gizlang
function JsonReader.number(self: mut JsonReader): f64
```

The next value as a number; 0 and an error when it is not a number.

Effects: fail.

### `JsonReader.integer`

```gizlang
function JsonReader.integer(self: mut JsonReader): Option<i64>
```

A valid decimal integer token in i64's range; no floating point conversion.
Fractions, exponents and out-of-range integers are consumed and return none.

Effects: fail.

### `JsonReader.string`

```gizlang
function JsonReader.string(self: mut JsonReader): string
```

The next value as a string; empty and an error when it is not a string.

Effects: fail.

### `JsonReader.boolean`

```gizlang
function JsonReader.boolean(self: mut JsonReader): bool
```

The next value as a boolean; false and an error when it is not a boolean.

Effects: fail.

### `JsonReader.isNull`

```gizlang
function JsonReader.isNull(self: mut JsonReader): bool
```

Probe null: consumes it on a match, leaves other values for a typed read.

Effects: fail.

### `f64.writeJson`

```gizlang
function f64.writeJson(self: f64, out: mut bytes): void
```

Writes the number as JSON.

Effects: fail.

### `i64.writeJson`

```gizlang
function i64.writeJson(self: i64, out: mut bytes): void
```

Writes the integer as JSON.

Effects: fail.

### `bool.writeJson`

```gizlang
function bool.writeJson(self: bool, out: mut bytes): void
```

Writes the boolean as JSON.

Effects: fail.

### `string.writeJson`

```gizlang
function string.writeJson(self: string, out: mut bytes): void
```

Writes the string as JSON, with escapes.

Effects: fail.

### `Json.writeJson`

```gizlang
function Json.writeJson(self: Json, out: mut bytes): void
```

Writes the value as compact JSON.

Effects: fail.

### `Vec.writeJson`

```gizlang
function Vec.writeJson<T>(self: Vec<T>, out: mut bytes): void
```

Writes the vector as a JSON array.

### `Option.writeJson`

```gizlang
function Option.writeJson<T>(self: Option<T>, out: mut bytes): void
```

Writes the value, or null for none.

### `Map.writeJson`

```gizlang
function Map.writeJson<V>(self: Map<string, V>, out: mut bytes): void
```

Writes the map as a JSON object.

### `f64.readJson`

```gizlang
function f64.readJson(self: mut f64, json: Json): void throws JsonError
```

Reads a JSON number. It fails on any other value.

### `i64.readJson`

```gizlang
function i64.readJson(self: mut i64, json: Json): void throws JsonError
```

Reads a JSON number that is an integer. It fails on any other value.

Effects: fail.

### `bool.readJson`

```gizlang
function bool.readJson(self: mut bool, json: Json): void throws JsonError
```

Reads a JSON boolean. It fails on any other value.

### `string.readJson`

```gizlang
function string.readJson(self: mut string, json: Json): void throws JsonError
```

Reads a JSON string. It fails on any other value.

### `Json.readJson`

```gizlang
function Json.readJson(self: mut Json, json: Json): void throws JsonError
```

Takes the JSON value as it is.

### `Vec.readJson`

```gizlang
function Vec.readJson<T>(self: mut Vec<T>, json: Json): void throws JsonError
```

Reads a JSON array, each item as T. It fails on any other value.

### `Option.readJson`

```gizlang
function Option.readJson<T>(self: mut Option<T>, json: Json): void throws JsonError
```

Reads null as none, and any other value as T.

### `Map.readJson`

```gizlang
function Map.readJson<V>(self: mut Map<string, V>, json: Json): void throws JsonError
```

Reads a JSON object, each value as V. It fails on any other value.

## Constants

### `RPC_VERSION`

```gizlang
const RPC_VERSION = "2.0"
```

The JSON-RPC version that requests and answers carry.

### `RPC_PARSE_ERROR`

```gizlang
const RPC_PARSE_ERROR = -32700
```

JSON-RPC error: the request is not valid JSON.

### `RPC_INVALID_REQUEST`

```gizlang
const RPC_INVALID_REQUEST = -32600
```

JSON-RPC error: the JSON is not a valid request.

### `RPC_METHOD_NOT_FOUND`

```gizlang
const RPC_METHOD_NOT_FOUND = -32601
```

JSON-RPC error: the method does not exist.

### `RPC_INVALID_PARAMS`

```gizlang
const RPC_INVALID_PARAMS = -32602
```

JSON-RPC error: the parameters are not valid for the method.

### `RPC_INTERNAL_ERROR`

```gizlang
const RPC_INTERNAL_ERROR = -32603
```

JSON-RPC error: the server failed while it ran the method.

### `MAX_SAFE_INTEGER`

```gizlang
const MAX_SAFE_INTEGER = 9007199254740991
```

The greatest integer that a double, and so a JavaScript number, holds exactly.

