Axle v0.14.1
Package

std/text/json

std/json — JSON validation + string-builder helpers.

Two surfaces:

1. Validation — jsonValidate(text) is a recursive-descent
yes/no check, allocating no output tree — pure Axle over byte
indexing, no FFI.

2. Stringification helpers — escape / quote / primitive
converters so user code can emit JSON by concatenation without
reinventing the escape rules.

The escaping, validation and integer / bool / null converters are
pure Axle. jsonF64ToString stays native (exact IEEE-754 float
formatting, with NaN / ∞ mapped to null). Every structural ASCII
byte is named once, at module scope, in the const block below.

Free functions

TypeMethod and description
bool
__jsonIsWs(byte : i32) : bool true for JSON's whitespace set (space, tab, LF, CR).
bool
__jsonIsDigit(byte : i32) : bool true for an ASCII decimal digit.
i64
__jsonSkipWs(src : string, pos : i64, len : i64) : i64 Position of the first non-whitespace byte at or after pos.
i64
__jsonEat(src : string, pos : i64, len : i64, expected : i32) : i64 Consume one expected byte; returns pos + 1 or -1 if it doesn't match.
i64
__jsonEatKeyword(src : string, pos : i64, len : i64, keyword : string) : i64 Consume the literal keyword byte-for-byte (no allocation); -1 on mismatch.
i64
__jsonParseValue(src : string, pos : i64, len : i64) : i64 Any JSON value: object, array, string, keyword literal or number.
i64
__jsonParseObject(src : string, pos : i64, len : i64) : i64 { (string ':' value (',' string ':' value)*)? }.
i64
__jsonParseArray(src : string, pos : i64, len : i64) : i64 [ value (',' value)* ]?.
i64
__jsonParseString(src : string, pos : i64, len : i64) : i64 A quoted string, its escapes checked but not decoded (validation
only). \" \\ \/ \b \f \n \r \t are the short escapes;
\uXXXX needs exactly 4 hex digits; any other byte after \ is
invalid, and raw control bytes (< 0x20) are rejected unescaped.
i64
__jsonParseNumber(src : string, pos : i64, len : i64) : i64 A JSON number: optional -, integer part, optional fraction, optional exponent.
bool
jsonValidate(text : string) : bool Recursive-descent yes/no validity check, allocating no output tree —
use it to gate untrusted input before further processing.
i64
__escapeInto(buffer : ptr<i8>, offset : i64, src : string) : i64 Escape the bytes of src into buffer at offset using JSON rules:
" \ \n \r \t \b \f get their short escapes, other control bytes
(< 0x20) become \u00XX, and every other byte is copied verbatim
(so valid UTF-8 round-trips). Returns the offset past the output.
string
jsonEscapeString(s : string) : string String escaping (the body without surrounding quotes — useful when
concatenating into a larger structure).
string
jsonQuoteString(s : string) : string Full quoted form: "..." with inner escaping.
string
jsonI64ToString(v : i64) : string Decimal text of a signed 64-bit value (digits emitted
least-significant-first then reversed; handles the minimum value
without negating).
string
jsonF64ToString(v : f64) : string Float → JSON literal. Stays native: NaN / ±∞ map to null, finite
values use the exact IEEE-754 shortest round-trip form.
string
jsonBoolToString(v : bool) : string The JSON literal true or false.
string
jsonNull() : string The JSON literal null.
bool
__jsonKeyEquals(src : string, start : i64, end : i64, key : string) : bool Does the quoted key at start (its opening quote) and ending at end
(past its closing quote) spell key?

Compared as bytes when the span carries no escape, which is every key an
API sends; a span holding one is decoded first, so "a\\u0062" still
matches "ab".
string
__jsonDecodeString(src : string, start : i64, end : i64) : string The quoted string spanning [start, end) — start at its opening quote,
end past its closing one — with its escapes decoded.

A lone surrogate, or a high surrogate with no low one after it, encodes as
U+FFFD: [__txtPutUtf8] refuses to emit a surrogate, and a decoder that
dropped the byte instead would shorten the string a caller measured.
i32
__jsonHex4(src : string, pos : i64, stop : i64) : i32 The scalar four hex digits at pos spell, or U+FFFD when they do not.
i64
__jsonMember(src : string, pos : i64, len : i64, key : string) : i64 Byte position of the value bound to key in the object starting at pos,
or -1 when there is no such member — or when pos does not start an
object at all, which is the same answer for the same reason: the caller
asked for a field and there is none.

The loop is the one in __jsonParseObject, written once more because that
one discards the two positions this needs. Validation already ran, so a
malformed shape here is impossible rather than merely unhandled.
string
__jsonSpan(src : string, start : i64, end : i64) : string The raw bytes of src[start..end) as a string — no escape handling.

Method detail

#__jsonIsWs

__jsonIsWs(byte : i32) : bool

true for JSON's whitespace set (space, tab, LF, CR).

#__jsonIsDigit

__jsonIsDigit(byte : i32) : bool

true for an ASCII decimal digit.

#__jsonSkipWs

__jsonSkipWs(src : string, pos : i64, len : i64) : i64

Position of the first non-whitespace byte at or after pos.

#__jsonEat

__jsonEat(src : string, pos : i64, len : i64, expected : i32) : i64

Consume one expected byte; returns pos + 1 or -1 if it doesn't match.

#__jsonEatKeyword

__jsonEatKeyword(src : string, pos : i64, len : i64, keyword : string) : i64

Consume the literal keyword byte-for-byte (no allocation); -1 on mismatch.

#__jsonParseValue

__jsonParseValue(src : string, pos : i64, len : i64) : i64

Any JSON value: object, array, string, keyword literal or number.

#__jsonParseObject

__jsonParseObject(src : string, pos : i64, len : i64) : i64

{ (string ':' value (',' string ':' value)*)? }.

#__jsonParseArray

__jsonParseArray(src : string, pos : i64, len : i64) : i64

[ value (',' value)* ]?.

#__jsonParseString

__jsonParseString(src : string, pos : i64, len : i64) : i64

A quoted string, its escapes checked but not decoded (validation
only). \" \\ \/ \b \f \n \r \t are the short escapes;
\uXXXX needs exactly 4 hex digits; any other byte after \ is
invalid, and raw control bytes (< 0x20) are rejected unescaped.

#__jsonParseNumber

__jsonParseNumber(src : string, pos : i64, len : i64) : i64

A JSON number: optional -, integer part, optional fraction, optional exponent.

#jsonValidate

jsonValidate(text : string) : bool

Recursive-descent yes/no validity check, allocating no output tree —
use it to gate untrusted input before further processing.

Parameters
text candidate JSON document to validate

#__escapeInto

__escapeInto(buffer : ptr<i8>, offset : i64, src : string) : i64

Escape the bytes of src into buffer at offset using JSON rules:
" \ \n \r \t \b \f get their short escapes, other control bytes
(< 0x20) become \u00XX, and every other byte is copied verbatim
(so valid UTF-8 round-trips). Returns the offset past the output.

Parameters
buffer destination byte buffer (as a raw address)
offset write position within the buffer to start at
src source string whose bytes to JSON-escape

#jsonEscapeString

jsonEscapeString(s : string) : string

String escaping (the body without surrounding quotes — useful when
concatenating into a larger structure).

Parameters
s string to JSON-escape (no surrounding quotes added)

#jsonQuoteString

jsonQuoteString(s : string) : string

Full quoted form: "..." with inner escaping.

Parameters
s string to escape and wrap in JSON double quotes

#jsonI64ToString

jsonI64ToString(v : i64) : string

Decimal text of a signed 64-bit value (digits emitted
least-significant-first then reversed; handles the minimum value
without negating).

Parameters
v signed integer to render as a JSON number

#jsonF64ToString

jsonF64ToString(v : f64) : string

Float → JSON literal. Stays native: NaN / ±∞ map to null, finite
values use the exact IEEE-754 shortest round-trip form.

Parameters
v floating-point value to render as a JSON number

#jsonBoolToString

jsonBoolToString(v : bool) : string

The JSON literal true or false.

Parameters
v bool to render as a JSON literal

#jsonNull

jsonNull() : string

The JSON literal null.

#__jsonKeyEquals

__jsonKeyEquals(src : string, start : i64, end : i64, key : string) : bool

Does the quoted key at start (its opening quote) and ending at end
(past its closing quote) spell key?

Compared as bytes when the span carries no escape, which is every key an
API sends; a span holding one is decoded first, so "a\\u0062" still
matches "ab".

#__jsonDecodeString

__jsonDecodeString(src : string, start : i64, end : i64) : string

The quoted string spanning [start, end) — start at its opening quote,
end past its closing one — with its escapes decoded.

A lone surrogate, or a high surrogate with no low one after it, encodes as
U+FFFD: [__txtPutUtf8] refuses to emit a surrogate, and a decoder that
dropped the byte instead would shorten the string a caller measured.

#__jsonHex4

__jsonHex4(src : string, pos : i64, stop : i64) : i32

The scalar four hex digits at pos spell, or U+FFFD when they do not.

#__jsonMember

__jsonMember(src : string, pos : i64, len : i64, key : string) : i64

Byte position of the value bound to key in the object starting at pos,
or -1 when there is no such member — or when pos does not start an
object at all, which is the same answer for the same reason: the caller
asked for a field and there is none.

The loop is the one in __jsonParseObject, written once more because that
one discards the two positions this needs. Validation already ran, so a
malformed shape here is impossible rather than merely unhandled.

#__jsonSpan

__jsonSpan(src : string, start : i64, end : i64) : string

The raw bytes of src[start..end) as a string — no escape handling.

C class Json

Constructors

TypeMethod and description
constructor(text : string) Take a cursor over text without validating it — parse is
the entry point, and this is what it calls once the document has been
checked.

Safe on a malformed document all the same: every accessor answers the
neutral value on a shape it cannot read, so an unchecked cursor simply
answers nothing rather than reading past anything.

Method detail

#constructor

constructor(text : string)

Take a cursor over text without validating it — parse is
the entry point, and this is what it calls once the document has been
checked.

Safe on a malformed document all the same: every accessor answers the
neutral value on a shape it cannot read, so an unchecked cursor simply
answers nothing rather than reading past anything.

Methods

Method detail

#parse

parse(text : string) : Json ! ParseException

#has

has(self, key : string) : bool

#text

text(self, key : string) : string

#int

int(self, key : string) : i64

#num

num(self, key : string) : f64

#flag

flag(self, key : string) : bool