github.com/kaptinlin/jsonschema@v0.4.6/readme.md (about) 1 # JSON Schema Validator for Go 2 3 [](https://golang.org/) 4 [](LICENSE) 5 [](https://github.com/json-schema-org/JSON-Schema-Test-Suite) 6 7 A high-performance JSON Schema validator for Go with **direct struct validation**, **smart unmarshaling** with defaults, and **separated validation workflow**. 8 9 ## Features 10 11 - ✅ **JSON Schema Draft 2020-12** - Full spec compliance 12 - ✅ **Direct Struct Validation** - Zero-copy validation without JSON marshaling 13 - ✅ **Separated Workflow** - Validation and unmarshaling as distinct operations 14 - ✅ **Type-Specific Methods** - Optimized paths for JSON, structs, and maps 15 - ✅ **Schema References** - Full `$ref`, `$recursiveRef`, `$dynamicRef` support 16 - ✅ **Custom Formats** - Register your own validators 17 - ✅ **Internationalization** - Multi-language error messages 18 - ✅ **Code Construction** - Type-safe schema building using JSON Schema keywords 19 20 ## Quick Start 21 22 ### Installation 23 24 ```bash 25 go get github.com/kaptinlin/jsonschema 26 ``` 27 28 ### Basic Usage 29 30 ```go 31 import "github.com/kaptinlin/jsonschema" 32 33 // Compile schema 34 compiler := jsonschema.NewCompiler() 35 schema, err := compiler.Compile([]byte(`{ 36 "type": "object", 37 "properties": { 38 "name": {"type": "string", "minLength": 1}, 39 "age": {"type": "integer", "minimum": 0} 40 }, 41 "required": ["name"] 42 }`)) 43 44 // Recommended workflow: validate first, then unmarshal 45 data := []byte(`{"name": "John", "age": 25}`) 46 47 // Step 1: Validate 48 result := schema.Validate(data) 49 if result.IsValid() { 50 fmt.Println("✅ Valid") 51 // Step 2: Unmarshal validated data 52 var user User 53 err := schema.Unmarshal(&user, data) 54 if err != nil { 55 log.Fatal(err) 56 } 57 } else { 58 fmt.Println("❌ Invalid") 59 for field, err := range result.Errors { 60 fmt.Printf("- %s: %s\n", field, err.Message) 61 } 62 } 63 ``` 64 65 ### Type-Specific Validation 66 67 Choose the method that matches your data type for best performance: 68 69 ```go 70 // For JSON bytes - fastest JSON parsing 71 result := schema.ValidateJSON([]byte(`{"name": "John"}`)) 72 73 // For Go structs - zero-copy validation 74 result := schema.ValidateStruct(Person{Name: "John"}) 75 76 // For maps - optimal for pre-parsed data 77 result := schema.ValidateMap(map[string]interface{}{"name": "John"}) 78 79 // Auto-detect input type 80 result := schema.Validate(anyData) 81 ``` 82 83 ### Unmarshal with Defaults 84 85 ```go 86 type User struct { 87 Name string `json:"name"` 88 Country string `json:"country"` 89 Active bool `json:"active"` 90 } 91 92 // Schema with defaults 93 schemaJSON := `{ 94 "type": "object", 95 "properties": { 96 "name": {"type": "string"}, 97 "country": {"type": "string", "default": "US"}, 98 "active": {"type": "boolean", "default": true} 99 }, 100 "required": ["name"] 101 }` 102 103 schema, _ := compiler.Compile([]byte(schemaJSON)) 104 105 // Validation + Unmarshal workflow 106 data := []byte(`{"name": "John"}`) 107 result := schema.Validate(data) 108 if result.IsValid() { 109 var user User 110 err := schema.Unmarshal(&user, data) 111 // Result: user.Country = "US", user.Active = true 112 } 113 ``` 114 115 ### Dynamic Default Values 116 117 Register functions to generate dynamic defaults during unmarshaling: 118 119 ```go 120 // Register custom functions 121 compiler := jsonschema.NewCompiler() 122 compiler.RegisterDefaultFunc("now", jsonschema.DefaultNowFunc) 123 compiler.RegisterDefaultFunc("uuid", func(args ...any) (any, error) { 124 return uuid.New().String(), nil 125 }) 126 127 // Schema with dynamic defaults 128 schemaJSON := `{ 129 "type": "object", 130 "properties": { 131 "id": {"default": "uuid()"}, 132 "createdAt": {"default": "now()"}, 133 "formattedDate": {"default": "now(2006-01-02)"}, 134 "status": {"default": "active"} 135 } 136 }` 137 138 schema, _ := compiler.Compile([]byte(schemaJSON)) 139 140 // Input: {} 141 // Result: { 142 // "id": "3ace637a-515a-4328-a614-b3deb58d410d", 143 // "createdAt": "2025-06-05T01:05:22+08:00", 144 // "formattedDate": "2025-06-05", 145 // "status": "active" 146 // } 147 ``` 148 149 ## Programmatic Schema Building 150 151 Create JSON schemas directly in Go code with type-safe constructors: 152 153 ```go 154 // Define schemas with fluent API 155 schema := jsonschema.Object( 156 jsonschema.Prop("name", jsonschema.String(jsonschema.MinLen(1))), 157 jsonschema.Prop("email", jsonschema.Email()), 158 jsonschema.Required("name", "email"), 159 ) 160 161 // Validate immediately - no compilation step 162 result := schema.Validate(data) 163 ``` 164 165 ### Key Features 166 167 - **Core Types**: String, Integer, Array, Object with validation keywords 168 - **Composition**: OneOf, AnyOf, AllOf, conditional logic (If/Then/Else) 169 - **Formats**: Built-in validators for email, UUID, datetime, URI, etc. 170 - **Registration**: Register schemas for reuse and cross-references 171 172 **📖 Full Documentation**: [docs/constructor.md](docs/constructor.md) 173 174 ### Custom Compiler for Schemas 175 176 Set custom compilers on schemas for isolated function registries: 177 178 ```go 179 // Create custom compiler with functions 180 compiler := jsonschema.NewCompiler() 181 compiler.RegisterDefaultFunc("now", jsonschema.DefaultNowFunc) 182 183 // Apply to programmatically built schema 184 schema := jsonschema.Object( 185 jsonschema.Prop("timestamp", jsonschema.String(jsonschema.Default("now()"))), 186 jsonschema.Prop("name", jsonschema.String()), 187 ).SetCompiler(compiler) 188 189 // Child schemas automatically inherit parent's compiler 190 result := schema.Validate(data) 191 ``` 192 193 ## Advanced Features 194 195 ### Custom Formats 196 197 ```go 198 compiler.RegisterFormat("uuid", func(value string) bool { 199 _, err := uuid.Parse(value) 200 return err == nil 201 }) 202 203 // Use in schema 204 schema := `{ 205 "type": "string", 206 "format": "uuid" 207 }` 208 ``` 209 210 ### Schema References 211 212 ```go 213 schema := `{ 214 "type": "object", 215 "properties": { 216 "user": {"$ref": "#/$defs/User"} 217 }, 218 "$defs": { 219 "User": { 220 "type": "object", 221 "properties": { 222 "name": {"type": "string"} 223 } 224 } 225 } 226 }` 227 ``` 228 229 ### Internationalization 230 231 ```go 232 // Set custom error messages 233 compiler.SetLocale("zh-CN") 234 235 // Or use custom translator 236 compiler.SetTranslator(func(key string, args ...interface{}) string { 237 return customTranslate(key, args...) 238 }) 239 ``` 240 241 ### Performance Optimization 242 243 ```go 244 // Pre-compile schemas for better performance 245 compiler := jsonschema.NewCompiler() 246 schema := compiler.MustCompile(schemaJSON) 247 248 // Use type-specific validation methods 249 result := schema.ValidateStruct(structData) // Fastest for structs 250 result := schema.ValidateJSON(jsonBytes) // Fastest for JSON 251 result := schema.ValidateMap(mapData) // Fastest for maps 252 ``` 253 254 ## Error Handling 255 256 ### Detailed Error Information 257 258 ```go 259 result := schema.Validate(data) 260 if !result.IsValid() { 261 // Get all errors 262 for field, err := range result.Errors { 263 fmt.Printf("Field: %s\n", field) 264 fmt.Printf("Message: %s\n", err.Message) 265 fmt.Printf("Value: %v\n", err.Value) 266 fmt.Printf("Schema: %v\n", err.Schema) 267 } 268 269 // Or get as a list 270 errors := result.ToList() 271 for _, err := range errors { 272 fmt.Printf("Error: %s\n", err.Error()) 273 } 274 } 275 ``` 276 277 ### Custom Error Messages 278 279 ```go 280 schema := `{ 281 "type": "string", 282 "minLength": 5, 283 "errorMessage": "Name must be at least 5 characters long" 284 }` 285 ``` 286 287 ## Testing 288 289 The library includes comprehensive tests and passes the official JSON Schema Test Suite: 290 291 ```bash 292 go test ./... 293 ``` 294 295 ### Benchmarks 296 297 ```bash 298 go test -bench=. -benchmem 299 ``` 300 301 ## Contributing 302 303 We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. 304 305 ### Development Setup 306 307 ```bash 308 git clone https://github.com/kaptinlin/jsonschema.git 309 cd jsonschema 310 go mod download 311 go test ./... 312 ``` 313 314 ## License 315 316 This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 317 318 ## Related Projects 319 320 - [JSON Schema](https://json-schema.org/) - The official JSON Schema specification 321 - [JSON Schema Test Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite) - Official test suite 322 - [Understanding JSON Schema](https://json-schema.org/understanding-json-schema/) - Comprehensive guide 323 324 ## Acknowledgments 325 326 - Thanks to the JSON Schema community for the excellent specification 327 - Inspired by other JSON Schema implementations in various languages 328 - Special thanks to all contributors who have helped improve this library