Skip to content

amritk/mjst

mjst — More JSON Schema Tools

Generate fast, type-safe TypeScript parsers, validators, and type definitions from JSON Schemas.

status license JSON Schema node bun vibe coded

Warning

mjst is pre-alpha. APIs and generated output will change without notice until 1.0.


What is mjst?

mjst is a monorepo of code-generation tools that turn a JSON Schema (Draft 2020-12) into TypeScript:

Output Description
Parsers Runtime functions that validate and coerce unknown input into typed values
Validators Lightweight predicate-style validation functions
Type definitions .d.ts types matching the schema, with documentation comments
Markdown Reference docs derived from the schema

The CLI (mjst) is the primary entry point; the underlying generators are also published as standalone packages.


How mjst compares

Most tools in this space pick a single lane — types or validation or docs. mjst generates the whole TypeScript surface from one schema, and it can also consume schemas authored in other libraries as input.

Types Validators Parsers / coercion Markdown docs Test data ² Multi-library input
mjst
json-schema-to-typescript
ajv (standalone)
quicktype 🟡
TypeBox · Zod · Valibot n/a ¹

✅ first-class · 🟡 partial · — not offered

¹ These libraries are a schema source rather than a competitor — mjst consumes them via @amritk/adapters.

² fast-check arbitraries for property testing plus concrete example values, via @amritk/generate-examples.

Benchmarks

mjst's validators are generated TypeScript — straight-line, monomorphic code with no generic dispatch. The exported validateX runs a tiny inlined boolean guard on the happy path and falls back to a separate error-collecting function only when input is actually invalid, so a valid-input check beats every other library measured — including the build-time transformer typia. The numbers below compare a generated mjst validator against typia, an Ajv-compiled function, a TypeBox-compiled checker, and a hand-written Zod schema on the same data.

Each schema also generates a boolean type-guard isX(input): input is X — a single flat predicate (no error array, no cold-path call) returning the same verdict as validateX. It is the inline-friendly equivalent of TypeBox's compiled check / typia's is, for the common "is this valid?" question where you don't need the error list; validateX remains the rich, error-collecting form.

Steady-state throughput (valid input, higher is better):

schema mjst (generated) typia (transformed) ajv (compiled) typebox (compiled) zod
small (4 fields) ~22M ops/s ~4.2M ops/s ~7.0M ops/s ~4.0M ops/s ~1.8M ops/s
order (nested + array) ~6.9M ops/s ~1.7M ops/s ~2.5M ops/s ~1.7M ops/s ~0.4M ops/s
assert-loose ~110M ops/s ~100M ops/s ~31M ops/s ~41M ops/s ~3.2M ops/s
assert-strict ~98M ops/s ~82M ops/s ~13M ops/s ~28M ops/s ~1.1M ops/s

The assert-loose / assert-strict rows are the exact shape used by moltar/typescript-runtime-type-benchmarks.

Prepare-a-validator cost (one-shot, lower is better):

mjst (codegen) ajv (compile) typebox (compile) zod
small ~0.15 ms ~13 ms ~0.12 ms n/a — authored in code
order ~0.20 ms ~14 ms ~0.21 ms n/a — authored in code

Measured on Bun 1.3 (Linux x64); micro-benchmark figures vary by machine and runtime. Each library is timed in an isolated process over a pool of distinct inputs, reporting the median of many trials (so the optimiser can't hoist or eliminate the work). Every library agrees on each valid/invalid verdict — parity is asserted before timing — and TypeBox is given uuid/email format checkers so every library does the same work. Reproduce with cd packages/generate-validators && bun run bench.

Parsing replicates both parse modes of the same benchmark over the libraries with a pure (non-mutating) parse operation. parseSafe asserts the types and strips undeclared keys (zod's .strip()); parseStrict asserts the types and rejects undeclared keys (zod's .strict()):

schema mjst (generated) zod (.parse) typebox (Value.Parse)
parseSafe — strip extras
small (4 fields) ~12M ops/s ~2.5M ops/s ~1.1M ops/s
order (nested + array) ~5.3M ops/s ~0.53M ops/s ~0.14M ops/s
assert (moltar shape) ~12M ops/s ~3.3M ops/s ~0.56M ops/s
parseStrict — reject extras
small (4 fields) ~17M ops/s ~1.6M ops/s ~1.5M ops/s
order (nested + array) ~3.4M ops/s ~0.30M ops/s ~0.23M ops/s
assert (moltar shape) ~9.4M ops/s ~1.1M ops/s ~0.79M ops/s

mjst parses in strict mode throughout (throwing on a type mismatch like the others), adding stripUnknown for parseSafe and additionalProperties: false for parseStrict; zod uses .object/.strictObject and TypeBox a Clean+Assert/Assert pipeline. Parity — identical parsed output, and rejection of every wrong-typed (and, in strict mode, extra-keyed) sample — is asserted before timing. ajv (removeAdditional) and typia (assertPrune) are excluded because they strip by mutating the input in place rather than returning a new value, which a reused input pool can't measure fairly. Reproduce with cd packages/generate-parsers && bun run bench.


Quick start

No install required — run it directly with your favourite package runner:

# npm
npx @amritk/mjst --schema ./schema.json --out-dir ./generated

# pnpm
pnpx @amritk/mjst --schema ./schema.json --out-dir ./generated

# yarn
yarn dlx @amritk/mjst --schema ./schema.json --out-dir ./generated

# bun
bunx @amritk/mjst --schema ./schema.json --out-dir ./generated

Or use a config file:

npx @amritk/mjst --config ./mjst.config.json

Tip

If you'd rather add it to a project, install it as a dev dependency:

npm install --save-dev @amritk/mjst   # or pnpm add -D / yarn add -D / bun add -d

Then use the shorter mjst command in npm scripts or via npx mjst.

See the CLI README for the full flag reference and config file examples.


Packages

Package Description
@amritk/mjst CLI — generates parsers, validators, and types from a schema
@amritk/generate-parsers Programmatic API for parser + type generation
@amritk/generate-validators Programmatic API for validator generation
@amritk/runtime-validators Runtime JSON Schema validation for schemas not known ahead of time
@amritk/generate-examples Programmatic API for fast-check arbitraries + example data generation
@amritk/generate-markdown Programmatic API for markdown documentation generation
@amritk/adapters Convert schemas from external libraries (TypeBox, Zod, …) into JSON Schema
@amritk/resolve-refs Resolve and inline JSON Schema / OpenAPI $refs, with a default-deny SSRF guard
@amritk/yaml Tiny, dependency-free YAML parser with exact source positions for diagnostics
@amritk/helpers Shared runtime helpers used by generated code

Requirements

  • Node.js ≥ 20 (or Bun ≥ 1.1) to run the CLI
  • TypeScript ≥ 5 in your consuming project

Contributing? You'll need Bun ≥ 1.1 — it's the package manager and bundler for this repo. See CONTRIBUTING.md.


Development

bun install
bun run test        # run the test suite
bun run check       # lint with biome
bun run build       # build all publishable packages

See .claude/architecture.md for monorepo layout and design notes, and CONTRIBUTING.md for contribution guidelines.


License

MIT

About

More JSON Schema Tools

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors