An RFC 8259 JSON engine and a jq-flavoured query language — strict parser with line/column errors, event-based streaming, and a compiled generator pipeline. Zero dependencies.
import { parse, query } from './src/index.js';
const doc = parse(storeJson);
query(doc, '.store.books[] | select(.price < 20) | .title');
// → ['Neuromancer']
query(doc, '{titles: [.store.books[].title], count: (.store.books | length)}');
// → [{ titles: ['Dune', 'Neuromancer', 'Sapiens'], count: 3 }]
query(doc, '[.. | numbers] | add');
// → [63]- Strict RFC 8259 parser — precise
line/columnon every error (Unexpected token '}' at line 4, column 1), surrogate-pair-aware escapes, zero tolerance for trailing commas / comments / leading zeros - Streaming parser — event-based scanning with full paths
(
store.books.0.title), no tree building - Query language — pipes, comma (multi-output),
select/map, object & array construction, recursive descent (..), arithmetic with type-aware+(numbers add, strings concat, arrays append, objects merge), alternative// - Compiled queries — each query compiles once into nested generators;
laziness is free (
first(...) | …never evaluates the rest) - Fuzz-tested — 300 random documents round-trip through
stringify ∘ parse; streaming events reconciled against hand-counted leaves; every malformed mutation throws WITH a position
Full grammar, operator semantics and the error model: docs/SPEC.md.
git clone https://github.com/sudeanb/jsonquest.git
cd jsonquest
node --test # 27 testsquery(doc, '{titles: [.store.books[].title]}');
// → [{ titles: ['Dune', 'Neuromancer', 'Sapiens'] }]//semantics: empty streams count as "no output" —false | // xyieldsfalsefirst (it IS an output), then falls back only on emptiness- the compiler is a generator pipeline: pipes are
yield*delegation, sofirstcan short-circuit an unbounded stream - duplicate object keys keep the last value (documented choice; the RFC permits any)
- no
|=update-assignment, no string interpolation\(...), no@base64-style format strings has/1is a roadmap item (use.["k"] != nulltoday)- the streaming parser is single-string (chunked async input is roadmap)