github.com/kaptinlin/jsonschema@v0.4.6/readme.md (about)

     1  # JSON Schema Validator for Go
     2  
     3  [![Go Version](https://img.shields.io/badge/go-%3E%3D1.21.1-blue)](https://golang.org/)
     4  [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
     5  [![Test Status](https://img.shields.io/badge/tests-passing-brightgreen)](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