Parsing JSON
Package: @lanexio/parser-grammar-json Stable
Layer: 2 (Grammar). Depends only on @lanexio/parser-core.
Runtime: Universal (browser, server, edge worker).
Overview
Section titled “Overview”parseJson implements a full iterative JSON parser conforming to RFC 8259 (also ECMA-404). It handles objects, arrays, strings, numbers, booleans, and null with a single-pass explicit-container-stack state machine. No recursion.
Input is always a Uint8Array. Output is always a LexTree. Malformed JSON produces JsonKind.Error nodes — parseJson never throws.
The parser passes all 375 JSONTestSuite cases: 95 valid (y_*), 183 invalid/rejected (n_*), and 33 never-throw (i_*).
Import
Section titled “Import”import { parseJson, JsonKind, JsonField, JSON_KIND_NAMES_BY_ID, jsonGrammar, type ParseJsonOptions, type JsonKindType,} from '@lanexio/parser-grammar-json';Parse a document
Section titled “Parse a document”import { parseJson } from '@lanexio/parser-grammar-json';
const encoder = new TextEncoder();const tree = parseJson(encoder.encode('{"key": [1, true, null]}'));
console.log(tree.nodeCount); // total nodesconsole.log(tree.root.kind); // Document root kind id (0x0800)parseJson accepts a Uint8Array. Always use TextEncoder when converting a string to bytes.
Nested structures
Section titled “Nested structures”const tree = parseJson(encoder.encode(`{ "users": [ { "id": 1, "name": "Alice" }, { "id": 2, "name": "Bob" } ]}`));// Walks: Document → Object → Member("users") → Array → Object → Member("id", Number(1)), ...Valid vs invalid
Section titled “Valid vs invalid”// Valid — produces Document → TrueparseJson(encoder.encode('true'));
// Invalid — produces Document → Error (never throws)const tree = parseJson(encoder.encode('{broken'));console.log(tree.root.child(0)?.kind === JsonKind.Error); // trueParseJsonOptions
Section titled “ParseJsonOptions”| Field | Type | Default | Description |
|---|---|---|---|
strict | boolean | undefined | Reserved for future use. Currently has no effect. |
Detect LexError nodes
Section titled “Detect LexError nodes”import { parseJson, JsonKind } from '@lanexio/parser-grammar-json';
const encoder = new TextEncoder();const tree = parseJson(encoder.encode('[1,]')); // trailing comma — RFC 8259 disallows
for (const node of tree.root.children()) { if (node.kind === JsonKind.Error) { console.log('parse error at', node.range); }}parseJson never throws. Invalid JSON produces JsonKind.Error nodes. The parser always recovers.
JsonKind constants
Section titled “JsonKind constants”import { JsonKind } from '@lanexio/parser-grammar-json';
// JsonKind is a const object. Use 'as const' pattern, never enum.const kind: JsonKindType = JsonKind.Array;
// Node kind IDs (0x0800 block)JsonKind.Document; // 0x0800JsonKind.Object; // 0x0801JsonKind.Member; // 0x0802JsonKind.Array; // 0x0803JsonKind.String; // 0x0804JsonKind.Number; // 0x0805JsonKind.True; // 0x0806JsonKind.False; // 0x0807JsonKind.Null; // 0x0808JsonKind.Whitespace; // 0x0809JsonKind.Error; // 0x080aJsonKind values are stable across versions. Never use raw numbers — always reference JsonKind.<name>.
Full exports
Section titled “Full exports”| Export | Type | Description |
|---|---|---|
parseJson | (bytes: Uint8Array, options?: ParseJsonOptions) => LexTree | Parse JSON RFC 8259. Never throws. |
ParseJsonOptions | { readonly strict?: boolean } | Options for parseJson. |
JsonKind | const object | Numeric kind IDs for all JSON node types (0x0800 block). |
JsonKindType | type union | Union of all JsonKind values. |
JSON_KIND_NAMES_BY_ID | Readonly<Record<number, string>> | Kind-name lookup by numeric ID. |
jsonGrammar | Lanexio ParserPureGrammar | Grammar descriptor for parser-pure. |
Conformance
Section titled “Conformance”| Metric | Value |
|---|---|
| JSONTestSuite y_ (valid) | 95 / 95 |
| JSONTestSuite n_ (rejected) | 183 / 183 |
| JSONTestSuite i_ (never-throw) | 33 / 33 |
| Total | 375 / 375 |
| verify:no-throw | 59 entry points |
| Fuzz soak (300s) | 11.7M rounds / 0 crashes |
Companion packages
Section titled “Companion packages”@lanexio/parser-core— shared buffer protocol,LexTree,LexNode,LexCursor.@lanexio/parser-pure— pure-TypeScript multi-grammar bridge; passjsonGrammartocreateParser.@lanexio/parser— unified entry point; importsparseJsonas an optional peer dependency.