A high-performance JSON Schema validator for Go with direct struct validation, smart unmarshaling with defaults, and separated validation workflow.
- β JSON Schema Draft 2020-12 - Full spec compliance
- β Direct Struct Validation - Zero-copy validation without JSON marshaling
- β Separated Workflow - Validation and unmarshaling as distinct operations
- β Type-Specific Methods - Optimized paths for JSON, structs, and maps
- β
Schema References - Full
$ref
,$recursiveRef
,$dynamicRef
support - β Custom Formats - Register your own validators
- β Internationalization - Multi-language error messages
- β Code Construction - Type-safe schema building using JSON Schema keywords
go get github.com/kaptinlin/jsonschema
import "github.com/kaptinlin/jsonschema"
// Compile schema
compiler := jsonschema.NewCompiler()
schema, err := compiler.Compile([]byte(`{
"type": "object",
"properties": {
"name": {"type": "string", "minLength": 1},
"age": {"type": "integer", "minimum": 0}
},
"required": ["name"]
}`))
// Recommended workflow: validate first, then unmarshal
data := []byte(`{"name": "John", "age": 25}`)
// Step 1: Validate
result := schema.Validate(data)
if result.IsValid() {
fmt.Println("β
Valid")
// Step 2: Unmarshal validated data
var user User
err := schema.Unmarshal(&user, data)
if err != nil {
log.Fatal(err)
}
} else {
fmt.Println("β Invalid")
for field, err := range result.Errors {
fmt.Printf("- %s: %s\n", field, err.Message)
}
}
Choose the method that matches your data type for best performance:
// For JSON bytes - fastest JSON parsing
result := schema.ValidateJSON([]byte(`{"name": "John"}`))
// For Go structs - zero-copy validation
result := schema.ValidateStruct(Person{Name: "John"})
// For maps - optimal for pre-parsed data
result := schema.ValidateMap(map[string]interface{}{"name": "John"})
// Auto-detect input type
result := schema.Validate(anyData)
type User struct {
Name string `json:"name"`
Country string `json:"country"`
Active bool `json:"active"`
}
// Schema with defaults
schemaJSON := `{
"type": "object",
"properties": {
"name": {"type": "string"},
"country": {"type": "string", "default": "US"},
"active": {"type": "boolean", "default": true}
},
"required": ["name"]
}`
schema, _ := compiler.Compile([]byte(schemaJSON))
// Validation + Unmarshal workflow
data := []byte(`{"name": "John"}`)
result := schema.Validate(data)
if result.IsValid() {
var user User
err := schema.Unmarshal(&user, data)
// Result: user.Country = "US", user.Active = true
}
Create JSON schemas directly in Go code with type-safe constructors:
// Define schemas with fluent API
schema := jsonschema.Object(
jsonschema.Prop("name", jsonschema.String(jsonschema.MinLen(1))),
jsonschema.Prop("email", jsonschema.Email()),
jsonschema.Required("name", "email"),
)
// Validate immediately - no compilation step
result := schema.Validate(data)
- Core Types: String, Integer, Array, Object with validation keywords
- Composition: OneOf, AnyOf, AllOf, conditional logic (If/Then/Else)
- Formats: Built-in validators for email, UUID, datetime, URI, etc.
- Registration: Register schemas for reuse and cross-references
π Full Documentation: docs/constructor.md
compiler.RegisterFormat("uuid", func(value string) bool {
_, err := uuid.Parse(value)
return err == nil
})
// Use in schema
schema := `{
"type": "string",
"format": "uuid"
}`
schema := `{
"type": "object",
"properties": {
"user": {"$ref": "#/$defs/User"}
},
"$defs": {
"User": {
"type": "object",
"properties": {
"name": {"type": "string"}
}
}
}
}`
// Set custom error messages
compiler.SetLocale("zh-CN")
// Or use custom translator
compiler.SetTranslator(func(key string, args ...interface{}) string {
return customTranslate(key, args...)
})
// Pre-compile schemas for better performance
compiler := jsonschema.NewCompiler()
schema := compiler.MustCompile(schemaJSON)
// Use type-specific validation methods
result := schema.ValidateStruct(structData) // Fastest for structs
result := schema.ValidateJSON(jsonBytes) // Fastest for JSON
result := schema.ValidateMap(mapData) // Fastest for maps
result := schema.Validate(data)
if !result.IsValid() {
// Get all errors
for field, err := range result.Errors {
fmt.Printf("Field: %s\n", field)
fmt.Printf("Message: %s\n", err.Message)
fmt.Printf("Value: %v\n", err.Value)
fmt.Printf("Schema: %v\n", err.Schema)
}
// Or get as a list
errors := result.ToList()
for _, err := range errors {
fmt.Printf("Error: %s\n", err.Error())
}
}
schema := `{
"type": "string",
"minLength": 5,
"errorMessage": "Name must be at least 5 characters long"
}`
The library includes comprehensive tests and passes the official JSON Schema Test Suite:
go test ./...
go test -bench=. -benchmem
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
git clone https://github.com/kaptinlin/jsonschema.git
cd jsonschema
go mod download
go test ./...
This project is licensed under the MIT License - see the LICENSE file for details.
- JSON Schema - The official JSON Schema specification
- JSON Schema Test Suite - Official test suite
- Understanding JSON Schema - Comprehensive guide
- Thanks to the JSON Schema community for the excellent specification
- Inspired by other JSON Schema implementations in various languages
- Special thanks to all contributors who have helped improve this library