jschema

spec-compliant JSON Schema (draft 2020-12) validator and builder for Nim

Pure Nim score 15/100 · tests present · no docs generated

Summary

Latest Version 0.1.0
License MIT
CI Status Failing
Downloads 0
Last Indexed 2026-07-22 05:30

Authors

  • Leon Lysak (Niminem)

Installation

nimble install jschema
choosenim install jschema
git clone https://github.com/Niminem/jschema

OS Compatibility

Platform Linux macOS Windows FreeBSD OpenBSD NetBSD Android iOS WASM Embedded
jschema - - - - - - -

Dependencies

Package Version Optional
nim >= 2.2.10 No

Source

Repository https://github.com/Niminem/jschema
Homepage https://github.com/Niminem/jschema
Registry Source nimble_official

README

jschema

JSON Schema (draft 2020-12) validator and builder for Nim. Standard lib only- no deps aside from std/re (libpcre library for regex which comes installed with Nim).

Spec-compliant against the entire official JSON Schema Test Suite for draft 2020-12, except the suite's optional tests (PRs welcome).

That includes the hard parts: $ref/$id/$anchor resolution, $dynamicRef/$dynamicAnchor, unevaluatedProperties/unevaluatedItems, $vocabulary-aware custom metaschemas, and infinite-recursion detection.

Installation

nimble install jschema

or

git clone https://github.com/Niminem/jschema

Validating

import std/json
import jschema

let schema = parseJson("""{
  "type": "object",
  "properties": {"name": {"type": "string", "minLength": 1}},
  "required": ["name"]
}""")

let res = validate(%*{"name": "Ada"}, schema)
assert res.valid

let bad = validate(%*{"name": ""}, schema)
for err in bad.errors:
  echo err.instanceLocation, " ", err.keywordLocation, ": ", err.message

A schema whose references can never terminate (e.g. {"$ref": "#"}) raises InfiniteRecursionError instead of overflowing the stack.

Multiple schema documents

There is no network fetching: referenced documents must be registered up front. A SchemaRegistry maps URIs to documents and can be shared across validate calls (indexing is idempotent). The eight official 2020-12 metaschemas are bundled and pre-registered in every new registry.

let registry = newSchemaRegistry()
registry.add("https://example.com/address.json", addressDoc)

# $ref: "https://example.com/address.json" now resolves.
let res = validate(data, schema, registry)

Building schemas

A fluent, typed builder produces plain JsonNode schemas. Keywords that collide with Nim keywords are renamed ($refrefTo, notnotSchema, if/then/elseifSchema/thenSchema/elseSchema, typejsonType, enumenumValues, constconstValue, $schemadialect).

let person = objectSchema()
  .properties({
    "name": stringSchema().minLength(1),
    "age": integerSchema().minimum(0),      # optional: not in required
  })
  .required("name")
  .additionalProperties(falseSchema())

assert validate(%*{"name": "Ada", "age": 36}, person).valid
let schemaJson = person.build                # the underlying JsonNode

Spec notes

  • format, content*, and meta-data keywords (default, title, ...) are annotation-only, which is the 2020-12 default. The format-assertion vocabulary is not implemented.
  • Regexes (pattern, patternProperties) use PCRE via std/re, not ECMA-262; the dialects differ in rare edge cases. libpcre is loaded at runtime — keep that next to your binary.
  • Only draft 2020-12 is supported.

Testing

The required suite tests are vendored under tests/draft2020-12/ with remote documents under tests/remotes/.

# One phase's tests during development (fails fast), t1 through t8:
nim r tests/t1_basics.nim

# The full required suite (exit code reflects failures):
nim r tests/test_suite.nim

The suite's optional/ tests (format-as-assertion, bignum, ECMA-262 regex semantics, ...) are not vendored or run — contributions welcome.