github.com/kaptinlin/jsonschema@v0.4.6/examples/multiple-input-types/main.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/kaptinlin/jsonschema"
     8  )
     9  
    10  // User struct for demonstrations
    11  type User struct {
    12  	Name    string `json:"name"`
    13  	Age     int    `json:"age"`
    14  	Email   string `json:"email,omitempty"`
    15  	Country string `json:"country,omitempty"`
    16  	Active  bool   `json:"active,omitempty"`
    17  }
    18  
    19  func main() {
    20  	// Setup schema with defaults
    21  	schema := setupSchema()
    22  
    23  	fmt.Println("Multiple Input Types Demo")
    24  	fmt.Println("========================")
    25  
    26  	// Demonstrate different input types
    27  	fmt.Println("\n1. Input Type Validation:")
    28  	demonstrateInputTypes(schema)
    29  
    30  	// Demonstrate unmarshal with defaults
    31  	fmt.Println("\n2. Unmarshal with Defaults:")
    32  	demonstrateUnmarshal(schema)
    33  
    34  	// Show best practices
    35  	fmt.Println("\n3. Best Practices:")
    36  	demonstrateBestPractices(schema)
    37  }
    38  
    39  func setupSchema() *jsonschema.Schema {
    40  	schemaJSON := `{
    41  		"type": "object",
    42  		"properties": {
    43  			"name": {"type": "string", "minLength": 1},
    44  			"age": {"type": "integer", "minimum": 0, "maximum": 150},
    45  			"email": {"type": "string", "format": "email"},
    46  			"country": {"type": "string", "default": "US"},
    47  			"active": {"type": "boolean", "default": true}
    48  		},
    49  		"required": ["name", "age"]
    50  	}`
    51  
    52  	compiler := jsonschema.NewCompiler()
    53  	schema, err := compiler.Compile([]byte(schemaJSON))
    54  	if err != nil {
    55  		log.Fatal("Failed to compile schema:", err)
    56  	}
    57  	return schema
    58  }
    59  
    60  func demonstrateInputTypes(schema *jsonschema.Schema) {
    61  	examples := []struct {
    62  		name  string
    63  		data  interface{}
    64  		emoji string
    65  	}{
    66  		{
    67  			name:  "JSON Bytes",
    68  			data:  []byte(`{"name": "Alice", "age": 28, "email": "alice@example.com"}`),
    69  			emoji: "πŸ“„",
    70  		},
    71  		{
    72  			name:  "Go Struct",
    73  			data:  User{Name: "Bob", Age: 35, Email: "bob@example.com"},
    74  			emoji: "πŸ—οΈ",
    75  		},
    76  		{
    77  			name: "Map Data",
    78  			data: map[string]interface{}{
    79  				"name":  "Charlie",
    80  				"age":   42,
    81  				"email": "charlie@example.com",
    82  			},
    83  			emoji: "πŸ—ΊοΈ",
    84  		},
    85  		{
    86  			name:  "JSON String (as []byte)",
    87  			data:  []byte(`{"name": "Diana", "age": 30}`),
    88  			emoji: "πŸ”€",
    89  		},
    90  	}
    91  
    92  	for _, example := range examples {
    93  		result := schema.Validate(example.data)
    94  		status := getStatusIcon(result.IsValid())
    95  		fmt.Printf("  %s %s %s: %s\n", example.emoji, example.name, status, getStatusText(result.IsValid()))
    96  	}
    97  }
    98  
    99  func demonstrateUnmarshal(schema *jsonschema.Schema) {
   100  	// Example 1: JSON bytes with defaults
   101  	fmt.Println("  πŸ“„ From JSON bytes:")
   102  	var user1 User
   103  	err := schema.Unmarshal(&user1, []byte(`{"name": "Eve", "age": 25}`))
   104  	if err != nil {
   105  		fmt.Printf("    ❌ Error: %v\n", err)
   106  	} else {
   107  		fmt.Printf("    βœ… Success: %s, age %d, country: %s (default), active: %t (default)\n",
   108  			user1.Name, user1.Age, user1.Country, user1.Active)
   109  	}
   110  
   111  	// Example 2: Map with defaults
   112  	fmt.Println("  πŸ—ΊοΈ From map data:")
   113  	var user2 User
   114  	mapData := map[string]interface{}{
   115  		"name":    "Frank",
   116  		"age":     40,
   117  		"country": "Canada",
   118  	}
   119  	err = schema.Unmarshal(&user2, mapData)
   120  	if err != nil {
   121  		fmt.Printf("    ❌ Error: %v\n", err)
   122  	} else {
   123  		fmt.Printf("    βœ… Success: %s, age %d, country: %s, active: %t (default)\n",
   124  			user2.Name, user2.Age, user2.Country, user2.Active)
   125  	}
   126  
   127  	// Example 3: Struct to struct
   128  	fmt.Println("  πŸ—οΈ From struct:")
   129  	var user3 User
   130  	sourceUser := User{Name: "Grace", Age: 33, Email: "grace@example.com"}
   131  	err = schema.Unmarshal(&user3, sourceUser)
   132  	if err != nil {
   133  		fmt.Printf("    ❌ Error: %v\n", err)
   134  	} else {
   135  		fmt.Printf("    βœ… Success: %s, age %d, country: %s (default), active: %t (default)\n",
   136  			user3.Name, user3.Age, user3.Country, user3.Active)
   137  	}
   138  }
   139  
   140  func demonstrateBestPractices(schema *jsonschema.Schema) {
   141  	fmt.Println("  πŸš€ Recommended approaches:")
   142  
   143  	// Best practice 1: JSON strings
   144  	fmt.Println("    β€’ For JSON strings, convert to []byte:")
   145  	jsonString := `{"name": "Henry", "age": 45}`
   146  	fmt.Printf("      jsonString := %s\n", jsonString)
   147  	fmt.Printf("      schema.Validate([]byte(jsonString)) // βœ… Recommended\n")
   148  
   149  	// Best practice 2: Error handling
   150  	fmt.Println("    β€’ Always check validation before unmarshal:")
   151  	fmt.Println("      result := schema.Validate(data)")
   152  	fmt.Println("      if result.IsValid() {")
   153  	fmt.Println("          schema.Unmarshal(&target, data)")
   154  	fmt.Println("      }")
   155  
   156  	// Best practice 3: Defaults
   157  	fmt.Println("    β€’ Use schema defaults for cleaner data:")
   158  	fmt.Println("      Define defaults in schema, not in Go structs")
   159  
   160  	// Demonstrate validation failure
   161  	fmt.Println("\n  ⚠️ Validation failure example:")
   162  	invalidData := []byte(`{"name": "", "age": -5}`) // Invalid data
   163  	result := schema.Validate(invalidData)
   164  	if !result.IsValid() {
   165  		fmt.Println("    Validation errors:")
   166  		for field, err := range result.Errors {
   167  			fmt.Printf("    - %s: %s\n", field, err.Message)
   168  		}
   169  	}
   170  }
   171  
   172  func getStatusIcon(isValid bool) string {
   173  	if isValid {
   174  		return "βœ…"
   175  	}
   176  	return "❌"
   177  }
   178  
   179  func getStatusText(isValid bool) string {
   180  	if isValid {
   181  		return "Valid"
   182  	}
   183  	return "Invalid"
   184  }