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

     1  # Validation Guide
     2  
     3  Complete guide to validation methods and input types.
     4  
     5  ## Validation Methods
     6  
     7  ### Universal Method
     8  
     9  #### schema.Validate(data interface{})
    10  
    11  Auto-detects input type and uses the optimal validation method.
    12  
    13  ```go
    14  // Works with any input type
    15  result := schema.Validate(jsonBytes)     // Detects JSON
    16  result := schema.Validate(structData)    // Detects struct
    17  result := schema.Validate(mapData)       // Detects map
    18  ```
    19  
    20  **When to use:** Mixed input types or quick prototyping.
    21  
    22  ---
    23  
    24  ### Type-Specific Methods
    25  
    26  Use these when you know your input type for best performance:
    27  
    28  #### schema.ValidateJSON(data []byte)
    29  
    30  Validates JSON byte arrays with optimized JSON parsing.
    31  
    32  ```go
    33  jsonData := []byte(`{"name": "John", "age": 30}`)
    34  result := schema.ValidateJSON(jsonData)
    35  
    36  if result.IsValid() {
    37      fmt.Println("✅ Valid JSON")
    38  }
    39  ```
    40  
    41  **Performance benefits:**
    42  - Single JSON parse operation
    43  - No type detection overhead
    44  - Direct JSON processing
    45  
    46  ---
    47  
    48  #### schema.ValidateStruct(data interface{})
    49  
    50  Validates Go structs directly using cached reflection.
    51  
    52  ```go
    53  type Person struct {
    54      Name string `json:"name"`
    55      Age  int    `json:"age"`
    56  }
    57  
    58  person := Person{Name: "John", Age: 30}
    59  result := schema.ValidateStruct(person)
    60  ```
    61  
    62  **Performance benefits:**
    63  - Uses cached reflection data
    64  - Zero-copy validation
    65  - No JSON marshaling overhead
    66  
    67  ---
    68  
    69  #### schema.ValidateMap(data map[string]interface{})
    70  
    71  Validates map data optimally for pre-parsed JSON.
    72  
    73  ```go
    74  data := map[string]interface{}{
    75      "name": "John",
    76      "age":  30,
    77  }
    78  result := schema.ValidateMap(data)
    79  ```
    80  
    81  **Performance benefits:**
    82  - Direct map processing
    83  - No conversion overhead
    84  - Optimal for pre-parsed JSON
    85  
    86  ---
    87  
    88  ## Input Types
    89  
    90  ### JSON Bytes ([]byte)
    91  
    92  The validator intelligently handles `[]byte` input:
    93  
    94  ```go
    95  // Valid JSON - parsed as JSON object/array
    96  jsonBytes := []byte(`{"name": "John", "age": 25}`)
    97  result := schema.Validate(jsonBytes)
    98  
    99  // Invalid JSON starting with { or [ - returns parse error
   100  malformedJSON := []byte(`{"name": "John", "age":`)
   101  result := schema.Validate(malformedJSON)
   102  
   103  // Binary data - treated as byte array
   104  binaryBytes := []byte{1, 2, 3, 4, 5}
   105  result := schema.Validate(binaryBytes)
   106  ```
   107  
   108  ### Go Structs
   109  
   110  Direct struct validation with JSON tag support:
   111  
   112  ```go
   113  type User struct {
   114      Name     string    `json:"name"`
   115      Age      int       `json:"age"`
   116      Email    string    `json:"email,omitempty"`
   117      Tags     []string  `json:"tags,omitempty"`
   118      Created  time.Time `json:"created_at"`
   119  }
   120  
   121  user := User{
   122      Name:  "Alice",
   123      Age:   28,
   124      Email: "alice@example.com",
   125  }
   126  result := schema.ValidateStruct(user)
   127  ```
   128  
   129  **Features:**
   130  - Respects `json` tags (field renaming, `omitempty`)
   131  - Handles nested structs
   132  - Supports pointers and slices
   133  - Time type support
   134  
   135  ### Maps and Interfaces
   136  
   137  Works with any map structure:
   138  
   139  ```go
   140  // Simple map
   141  data := map[string]interface{}{
   142      "name": "Bob",
   143      "age":  35,
   144  }
   145  
   146  // Nested map
   147  nested := map[string]interface{}{
   148      "user": map[string]interface{}{
   149          "name": "Charlie",
   150          "profile": map[string]interface{}{
   151              "bio": "Developer",
   152          },
   153      },
   154  }
   155  
   156  result := schema.ValidateMap(data)
   157  result := schema.ValidateMap(nested)
   158  ```
   159  
   160  ---
   161  
   162  ## Working with Results
   163  
   164  ### Basic Validation Check
   165  
   166  ```go
   167  result := schema.Validate(data)
   168  
   169  if result.IsValid() {
   170      fmt.Println("✅ Data is valid")
   171  } else {
   172      fmt.Println("❌ Validation failed")
   173  }
   174  ```
   175  
   176  ### Accessing Errors
   177  
   178  ```go
   179  result := schema.Validate(data)
   180  
   181  if !result.IsValid() {
   182      // Iterate through field errors
   183      for field, err := range result.Errors {
   184          fmt.Printf("Field '%s': %s\n", field, err.Message)
   185      }
   186  }
   187  ```
   188  
   189  ### Different Output Formats
   190  
   191  ```go
   192  result := schema.Validate(data)
   193  
   194  // Simple boolean flag
   195  flag := result.ToFlag()
   196  fmt.Printf("Valid: %t\n", flag.Valid)
   197  
   198  // Structured list
   199  list := result.ToList()
   200  for field, message := range list.Errors {
   201      fmt.Printf("%s: %s\n", field, message)
   202  }
   203  
   204  // Hierarchical structure (preserves nesting)
   205  hierarchical := result.ToList(true)  // includes hierarchy
   206  flat := result.ToList(false)         // flattened structure
   207  ```
   208  
   209  ---
   210  
   211  ## Performance Comparison
   212  
   213  | Method | Input Type | Parse Cost | Type Detection | Best For |
   214  |--------|------------|------------|----------------|----------|
   215  | `Validate` | Any | Variable | Yes | Mixed types |
   216  | `ValidateJSON` | `[]byte` | Once | No | JSON data |
   217  | `ValidateStruct` | Struct | None | No | Go structs |
   218  | `ValidateMap` | Map | None | No | Parsed JSON |
   219  
   220  ## Method Selection Guide
   221  
   222  **For JSON data:**
   223  ```go
   224  // Best performance for JSON
   225  result := schema.ValidateJSON(jsonBytes)
   226  ```
   227  
   228  **For Go structs:**
   229  ```go
   230  // Best performance for structs
   231  result := schema.ValidateStruct(structData)
   232  ```
   233  
   234  **For maps:**
   235  ```go
   236  // Best performance for maps
   237  result := schema.ValidateMap(mapData)
   238  ```
   239  
   240  **For mixed or unknown types:**
   241  ```go
   242  // Auto-detection with good performance
   243  result := schema.Validate(anyData)
   244  ```
   245  
   246  ## Error Handling Patterns
   247  
   248  ### Simple Error Check
   249  
   250  ```go
   251  result := schema.Validate(data)
   252  if !result.IsValid() {
   253      return fmt.Errorf("validation failed")
   254  }
   255  ```
   256  
   257  ### Detailed Error Reporting
   258  
   259  ```go
   260  result := schema.Validate(data)
   261  if !result.IsValid() {
   262      var errorMessages []string
   263      for field, err := range result.Errors {
   264          errorMessages = append(errorMessages, 
   265              fmt.Sprintf("%s: %s", field, err.Message))
   266      }
   267      return fmt.Errorf("validation errors: %s", 
   268          strings.Join(errorMessages, ", "))
   269  }
   270  ```
   271  
   272  ### Custom Error Handling
   273  
   274  ```go
   275  result := schema.Validate(data)
   276  if !result.IsValid() {
   277      for field, err := range result.Errors {
   278          switch err.Keyword {
   279          case "required":
   280              log.Printf("Missing required field: %s", field)
   281          case "type":
   282              log.Printf("Type mismatch for field: %s", field)
   283          case "minimum":
   284              log.Printf("Value too small for field: %s", field)
   285          default:
   286              log.Printf("Validation error for %s: %s", field, err.Message)
   287          }
   288      }
   289  }
   290  ```