Go module implementing JSON Schema validation following the JSON Schema 2020-12 specification — with a fluent schema builder, reusable compiled validators, and ahead-of-time validator code generation.
- Complete JSON Schema 2020-12 specification support
- All validation keywords (type, properties, items, etc.)
- Schema composition (allOf, anyOf, oneOf)
- Conditional schemas (if/then/else)
- Reference resolution ($ref, $anchor, $dynamicRef) — in-memory by default; network/filesystem access is opt-in
- Format validation (email, uri, date-time, etc.)
- Content validation (base64, json-pointer, etc.)
- Clean separation between schema construction and validation
- Build schemas using fluent builder API
- Compile schemas into optimized validators for high-performance validation
- Ahead-of-time code generation
- Emit a schema as standalone Go validator source, compiled straight into your binary
- No schema files to embed and no runtime schema compilation in production
- Command-line tool for schema validation and code generation
- Comprehensive test coverage including JSON Schema Test Suite compliance
Important
Reference resolution is in-memory by default — external access is opt-in.
A $ref/$dynamicRef to another document resolves only from schemas you
have registered in memory. The resolver does not reach out to the network
or read the local filesystem unless you explicitly enable it. This prevents
surprise outbound fetches (SSRF) and unexpected disk reads.
If you relied on the old behavior where external $refs were fetched
automatically, you must now opt in:
// Default: in-memory only. Preload externals with RegisterFS / RegisterDocument.
r := schema.NewResolver()
// Opt in to live access when you want it:
r = schema.NewResolver(schema.WithResolver(schema.HTTPResolver())) // HTTP/HTTPS
r = schema.NewResolver(schema.WithResolver(schema.DirResolver("."))) // local files under "."
r = schema.NewResolver(schema.WithResolver(schema.FSResolver(fsys))) // any io/fs (embed.FS, …)See References for details.
package examples_test
import (
"context"
"encoding/json"
"fmt"
"os"
schema "github.com/lestrrat-go/json-schema"
"github.com/lestrrat-go/json-schema/validator"
)
func Example() {
// Build a JSON Schema using the fluent builder API
userSchema := schema.NewBuilder().
Schema(schema.Version).
Types(schema.ObjectType).
Property("name", schema.NonEmptyString().MustBuild()).
Property("email", schema.Email().MustBuild()).
Property("age", schema.PositiveInteger().MustBuild()).
Required("name", "email").
MustBuild()
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
if err := enc.Encode(userSchema); err != nil {
fmt.Printf("failed to encode schema: %s\n", err)
return
}
// Compile the schema into an optimized validator
v, err := validator.Compile(context.Background(), userSchema)
if err != nil {
fmt.Printf("failed to compile validator: %s\n", err)
return
}
// Validate data
validUser := map[string]any{
"name": "John Doe",
"email": "john@example.com",
"age": 30,
}
_, err = v.Validate(context.Background(), validUser)
if err != nil {
fmt.Printf("validation failed: %s\n", err)
return
}
fmt.Println("User data is valid!")
// Test with invalid data
invalidUser := map[string]any{
"name": "", // Empty name should fail
"email": "not-an-email",
}
_, err = v.Validate(context.Background(), invalidUser)
if err != nil {
fmt.Printf("validation failed as expected: %s\n", err)
}
// OUTPUT:
// {
// "$schema": "https://json-schema.org/draft/2020-12/schema",
// "properties": {
// "age": {
// "minimum": 0,
// "type": "integer"
// },
// "email": {
// "format": "email",
// "type": "string"
// },
// "name": {
// "minLength": 1,
// "type": "string"
// }
// },
// "required": [
// "name",
// "email"
// ],
// "type": "object"
// }
// User data is valid!
// validation failed as expected: invalid value passed to ObjectValidator: property validation failed for name: invalid value passed to StringValidator: string length (0) shorter then minLength (1)
}source: examples/json_schema_readme_example_test.go
As a library:
go get github.com/lestrrat-go/json-schemaAs a command-line tool:
go install github.com/lestrrat-go/json-schema/cmd/json-schema@latestThe json-schema command line tool provides schema validation and code generation.
# Validate a schema file
json-schema lint schema.json
# Generate validator code
json-schema gen-validator --name UserValidator schema.json
# Read from stdin
echo '{"type": "string"}' | json-schema lint -Given a JSON schema file user-schema.json:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "User",
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"email": {
"type": "string",
"format": "email"
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150
}
},
"required": ["name", "email"],
"additionalProperties": false
}Generate a Go validator:
json-schema gen-validator --name UserValidator user-schema.jsonOutput:
UserValidator := validator.Object().
Required("name", "email").
Properties(
validator.PropPair("age", validator.Integer().Minimum(0).Maximum(150).MustBuild()),
validator.PropPair("email", validator.String().MustBuild()),
validator.PropPair("name", validator.String().MinLength(1).MustBuild()),
).
AdditionalProperties(false).
StrictObjectType(true).
MustBuild()This generated validator can be directly used in your Go code for high-performance validation.
- How-to Guides — building schemas, validating, references, vocabularies, code generation, and the CLI
- API Reference
- Runnable Examples
- Working on the library itself? See
AGENTS.md
This Go module implements JSON Schema validation according to the 2020-12 specification. The library provides a clean separation between schema construction and validation:
- Schema Construction: Build schemas using a fluent builder API or unmarshal from JSON
- Validator Compilation: Convert schemas into optimized validator objects for high-performance validation
- Validation: Use compiled validators to validate data with detailed error reporting
- Code Generation: Generate Go code that creates pre-compiled validators
| Package | Description |
|---|---|
| schema | Schema construction and builder API |
| validator | Validator compilation and validation logic |
| cmd/json-schema | Command-line tool for validation and code generation |
This library follows a clear separation of concerns:
- Schemas are pure data structures for representing JSON Schema documents
- Validators are compiled, optimized objects for performing validation
- Code Generation allows pre-compilation of validators for deployment scenarios
This design provides:
- High performance through compiled validators
- Clean, intuitive API
- Flexibility for different use cases
- Strong type safety
Most Go JSON Schema packages specialize in one direction — validating data, generating Go types from a schema, or inferring a schema from Go structs. This module instead covers the whole path from authoring to deployment:
- Author schemas with a fluent builder and ready-made constructors (
Email(),PositiveInteger(),Optional(), …), or unmarshal them from JSON — the two are interchangeable. - Compile a schema once into an optimized validator that is safe to reuse across goroutines and many requests.
- Generate that validator as plain Go source, so production binaries skip schema parsing and compilation entirely — a step most validators leave for runtime.
Schemas are fully encapsulated rather than open structs, so you cannot accidentally build a half-initialized or internally inconsistent schema, and the compiled form is free to optimize. The aim is one cohesive 2020-12 implementation that scales from a quick lint of a schema file to high-throughput services with no per-request setup.
For bug reports and feature requests, please try to follow the issue templates as much as possible. For either bug reports or feature requests, failing tests are even better.
Please make sure to include tests that exercise the changes you made.
See AGENTS.md for a map of the codebase, the build/test/codegen workflow, and architectural notes — it is written for both human contributors and AI coding agents.
If you are editing auto-generated files (those with the _gen.go suffix), please do the following:
- Edit the generator, not the generated files (e.g.
internal/cmd/genobjects/) - Run
./gen.shto regenerate the code - Commit both the generator and the generated files
Please try GitHub Discussions for usage questions and general discussion.