jschema
spec-compliant JSON Schema (draft 2020-12) validator and builder for Nim
Summary
| Latest Version | 0.1.0 |
|---|---|
| License | MIT |
| CI Status | Failing |
| Downloads | 0 |
| Last Indexed | 2026-07-22 05:30 |
Tags
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 ($ref → refTo, not →
notSchema, if/then/else → ifSchema/thenSchema/elseSchema,
type → jsonType, enum → enumValues, const → constValue,
$schema → dialect).
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 viastd/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.