jsonschema
A compliant, dependency-light Go library for compiling and validating JSON Schema across five draft versions, with rich hierarchical errors.
Repository Health
Technical Analysis
jsonschema is a Go library that compiles JSON Schema documents into an introspectable, thread-safe *Schema value and validates arbitrary JSON against it. It supports draft-4 through draft 2020-12 in a single compiler, auto-detecting the draft from a schema’s $schema property or falling back to a configurable default, so a single codebase can validate schemas written against different spec generations.
The library is built to pass the official JSON-Schema-Test-Suite (with only a documented set of optional cases excluded), which makes it one of the more spec-faithful Go implementations available. It resolves remote and recursive references, detects infinite reference loops before they become stack overflows, and supports draft 2019-09/2020-12 features like $recursiveRef, $dynamicRef, unevaluatedProperties, and unevaluatedItems.
Validation failures come back as a ValidationError with a full cause hierarchy addressable via JSON Pointers into both the schema and the instance document, and can be rendered as flag, basic, or detailed output per the JSON Schema output spec. A companion jv CLI (versioned independently under cmd/jv) wraps the same compiler for validating JSON or YAML files from the command line, including over HTTP(S) schema URLs.
The package name here — github.com/santhosh-tekuri/jsonschema/v5 — is the v5 major-version import path; the same repository has since moved on to a v6 module (import path .../jsonschema/v6) with a different public API, so projects pinned to v5 should treat this as a stable, frozen line rather than the latest release.
What You Get
- A
Compilertype that parses and compiles JSON Schema documents from file paths, HTTP(S) URLs, strings, byte slices, orio.Reader, resolving$refs (including remote and recursive references) along the way - Automatic draft detection from a schema’s
$schemaproperty (draft-4, draft-6, draft-7, draft 2019-09, draft 2020-12), with an explicitCompiler.Draftoverride when$schemais absent - A fully introspectable compiled
*Schemastruct exposing every keyword (types, properties, pattern properties, conditionals, numeric bounds, etc.) as public fields, useful for building tools like schema-to-struct generators - Rich
ValidationErrorvalues with a causal hierarchy and JSON-Pointer locations in both the schema and the instance document, plusFlagOutput(),BasicOutput(), andDetailedOutput()renderers matching the JSON Schema spec’s output formats - Support for user-defined format validators, content encodings/media types, and custom resource loaders, plus a keyword-extension mechanism for adding vocabulary beyond the spec
- An independently versioned
jvcommand-line tool (cmd/jv) that validates JSON or YAML documents against a schema, with configurable draft and output format flags
Common Use Cases
- Validating API request/response bodies against a JSON Schema in a Go HTTP service before further processing
- Enforcing configuration file correctness at startup by compiling a schema once and validating parsed YAML/JSON config against it
- Building developer tooling — e.g. generating Go structs or documentation from a compiled schema by walking its introspectable
Schemafields - Running
jvin CI to lint JSON/YAML fixtures or generated artifacts against a schema without writing any Go code - Cross-checking schemas that mix draft versions (via remote
$refs) in one validation pass, since the compiler resolves each referenced resource against its own declared draft
Under The Hood
Architecture
The library separates schema compilation from validation into two dense but distinct files: compiler.go walks a raw map[string]interface{} document and progressively fills a *Schema struct (schema.go) field by field, guarded by draft-version checks (r.draft.version >= N) and vocabulary checks (r.schema.meta.hasVocab("applicator")) so a single compiler correctly supports five spec generations without branching into five code paths. $ref/$recursiveRef/$dynamicRef resolution happens through a resource abstraction (root.go, roots.go) that tracks per-document base URLs and a stack []schemaRef used by checkLoop to detect infinite reference cycles before they blow the Go call stack. Validation (in validate) walks the compiled *Schema tree directly against a decoded interface{} value, threading an unevalProps/unevalItems result struct through nested calls so unevaluatedProperties/unevaluatedItems (added in later drafts) can see what sibling keywords already accounted for. The core abstraction change that would ripple furthest is the compiled Schema struct itself — it’s deliberately public and exhaustive, which is what enables the introspection use case but means any new keyword must be added there plus threaded through both compileMap and validate.
Tech Stack
Pure Go with a minimal dependency footprint: go.mod declares only golang.org/x/text (Unicode/text processing, likely for the hostname/IDNA-related format validators) as a runtime dependency, plus github.com/dlclark/regexp2 as a test-only dependency for exercising ECMA-style regex behavior. Numeric validation uses math/big.Rat throughout rather than float64, avoiding floating-point precision loss when checking minimum/maximum/multipleOf against large or fractional JSON numbers. An optional httploader subpackage (httploader/httploader.go) is imported separately (via a blank import of .../v5/httploader) to add HTTP(S) schema loading, keeping the core package free of a net/http dependency for consumers who only validate local schemas. The cmd/jv CLI is a separate Go module in the same repo, versioned independently from the library.
Code Quality
Testing relies heavily on the official JSON-Schema-Test-Suite pulled in as a git submodule (.gitmodules) and driven by schema_test.go, with an explicit skipTests variable documenting which optional suite cases are excluded and why — a notably transparent approach to spec-compliance claims. Additional unit tests cover formats (format_test.go), extensions (extension_test.go), and internal helpers (internal_test.go), and example files (example_test.go, example_extension_test.go) double as executable documentation via Go’s example-test convention. Error handling favors explicit error returns (*SchemaError, *ValidationError, InfiniteLoopError, InvalidJSONTypeError) over panics, aside from a deliberate panic/recover pair in validateValue used to unwind deeply recursive validation on loop detection. CI (.github/workflows/go.yaml) runs go vet and the test suite; a .golangci.yml config indicates linting is part of the standard workflow, though it is not enforced as a blocking CI step in this snapshot.
What Makes It Unique
Most Go JSON Schema libraries pick one draft version and validate against it; this one compiles a single document against whichever draft its $schema declares, letting an application load schemas authored at different spec generations (and referencing each other) inside one process without maintaining parallel validators. The fully public, introspectable Schema struct is unusual among validators-as-libraries — it’s designed to be walked by other tools (schema-to-struct generators, documentation generators), not just called via a black-box Validate(v) method. Combined with big.Rat-based numeric comparison and an extension mechanism for custom keywords, the library leans toward being a general-purpose JSON Schema toolkit rather than a narrowly scoped validation function.
Used by 2 apps in this directory
Rill
Analytics · Data Engineering
The fastest BI tool for humans and agents — define metrics, models, and dashboards as code and query them instantly on ClickHouse or DuckDB.
ZITADEL
Authentication
Open-source, API-first identity platform delivering multi-tenancy, Passkeys, OIDC, SAML, and SCIM without vendor lock-in.