Skip to content

Fluent, type-safe schema validation and JSON Schema generation for Go. Supports strings, numbers, arrays, objects, unions, conditionals, nullable/optional fields, custom errors, formats, and full i18n error messaging. Build complex validation logic with a clean, chainable API and export standard JSON Schema.

License

Notifications You must be signed in to change notification settings

nyxstack/schema

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NYX Schema

A powerful, fluent Go library for schema validation and JSON Schema generation with internationalization support.

Go Version License

Features

  • Fluent API: Chainable method calls for intuitive schema construction
  • Type Safety: Strong typing with validation for primitives, objects, arrays, and unions
  • JSON Schema Generation: Export schemas as standard JSON Schema format
  • Internationalization: Built-in i18n support for error messages
  • Comprehensive Validation: Support for all common validation constraints
  • Advanced Schema Types: AllOf, AnyOf, OneOf, Not, and conditional schemas
  • Format Validation: Built-in support for email, URI, UUID, date-time, and more
  • Custom Error Messages: Override default validation messages with custom ones
  • Nullable & Optional: Fine-grained control over required fields and null values

Installation

go get github.com/nyxstack/schema

Documentation

For comprehensive documentation on all schema types, including detailed examples and API references:

📚 View Full Documentation →

Quick links to specific schema types:

View all schema types →

Quick Start

package main

import (
    "fmt"
    "github.com/nyxstack/schema"
)

func main() {
    // Create a string schema with validation
    nameSchema := schema.String().
        Title("Full Name").
        Description("User's full name").
        MinLength(2).
        MaxLength(50).
        Pattern("^[a-zA-Z\\s]+$").
        Required()

    // Validate data
    ctx := schema.DefaultValidationContext()
    result := nameSchema.Parse("John Doe", ctx)
    
    if result.Valid {
        fmt.Printf("Valid name: %v\n", result.Value)
    } else {
        for _, err := range result.Errors {
            fmt.Printf("Error: %s\n", err.Message)
        }
    }
}

Core Schema Types

String Schema

// Basic string validation
emailSchema := schema.String().
    Email().
    Required("Email is required").
    MinLength(5, "Email too short")

// Pattern validation
usernameSchema := schema.String().
    Pattern("^[a-zA-Z0-9_]+$").
    MinLength(3).
    MaxLength(20)

// Enum validation
statusSchema := schema.String().
    Enum([]string{"active", "inactive", "pending"})

Number Schema

// Integer validation
ageSchema := schema.Int().
    Min(0).
    Max(120).
    Required()

// Float validation
priceSchema := schema.Float().
    Min(0.01).
    Max(9999.99).
    MultipleOf(0.01)

Array Schema

// Array of strings
tagsSchema := schema.Array(schema.String().MinLength(1)).
    MinItems(1).
    MaxItems(10).
    UniqueItems()

// Complex array validation
usersSchema := schema.Array(
    schema.Object().
        Property("name", schema.String().Required()).
        Property("email", schema.String().Email().Required()),
).MinItems(1)

Object Schema

// Structured object validation
userSchema := schema.Object().
    Property("id", schema.Int().Min(1).Required()).
    Property("name", schema.String().MinLength(2).Required()).
    Property("email", schema.String().Email().Required()).
    Property("age", schema.Int().Min(13).Max(120).Optional()).
    Property("tags", schema.Array(schema.String()).Optional()).
    AdditionalProperties(false)

// Using Shape for concise object creation
user := schema.Shape{
    "name":  schema.String().Required(),
    "email": schema.String().Email().Required(),
    "age":   schema.Int().Min(0).Optional(),
}.AsObject()

Record Schema

// Record schema for key-value maps with dynamic keys
metadataSchema := schema.Record(
    schema.String().MinLength(1), // Key schema
    schema.String().MinLength(1), // Value schema
).MinProperties(1).MaxProperties(10)

// Example: validate a map of string labels
labelsSchema := schema.Record(
    schema.String().Pattern("^[a-z0-9-]+$"), // Keys must be lowercase with dashes
    schema.String().MaxLength(100),           // Values max 100 chars
)

Union Types

// AnyOf - value matches at least one schema
stringOrNumber := schema.AnyOf(
    schema.String().MinLength(1),
    schema.Int().Min(0),
)

// OneOf - value matches exactly one schema
idSchema := schema.OneOf(
    schema.String().Pattern("^[a-zA-Z0-9_]+$"),
    schema.Int().Min(1),
)

// AllOf - value matches all schemas
restrictiveString := schema.AllOf(
    schema.String().MinLength(8),
    schema.String().Pattern(".*[A-Z].*"),
    schema.String().Pattern(".*[0-9].*"),
)

Advanced Features

Conditional Validation

conditionalSchema := schema.Conditional().
    If(schema.Object().Property("type", schema.String().Const("premium"))).
    Then(schema.Object().Property("features", schema.Array(schema.String()).MinItems(3))).
    Else(schema.Object().Property("features", schema.Array(schema.String()).MaxItems(1)))

Custom Error Messages

schema := schema.String().
    MinLength(8, "Password must be at least 8 characters").
    Pattern(".*[A-Z].*", "Password must contain uppercase letter").
    Required("Password is mandatory")

Nullable and Optional

// Optional field (can be omitted)
optionalField := schema.String().Optional()

// Nullable field (can be null)
nullableField := schema.String().Nullable()

// Both optional and nullable
flexibleField := schema.String().Optional().Nullable()

Format Validation

// Built-in formats
emailSchema := schema.String().Email()
urlSchema := schema.String().URL()
uuidSchema := schema.String().UUID()
dateSchema := schema.String().DateTime()

// Custom format with pattern
phoneSchema := schema.String().
    Format(schema.StringFormat("phone")).
    Pattern("^\\+?[1-9]\\d{1,14}$")

Validation Context

// Default English context
ctx := schema.DefaultValidationContext()

// Custom locale for internationalization
ctx := schema.NewValidationContext("es") // Spanish

// With Go context
ctx := schema.DefaultValidationContext().
    WithContext(context.Background())

JSON Schema Generation

userSchema := schema.Object().
    Property("name", schema.String().Required()).
    Property("email", schema.String().Email().Required())

// Generate JSON Schema
jsonSchema := userSchema.JSON()

// Convert to JSON
jsonBytes, _ := json.Marshal(jsonSchema)
fmt.Println(string(jsonBytes))

Output:

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "email": {
      "type": "string",
      "format": "email"
    }
  },
  "required": ["name", "email"],
  "additionalProperties": false
}

Error Handling

result := schema.Parse(data, ctx)

if !result.Valid {
    for _, err := range result.Errors {
        fmt.Printf("Field: %v\n", err.Path)
        fmt.Printf("Value: %s\n", err.Value)
        fmt.Printf("Error: %s\n", err.Message)
        fmt.Printf("Code: %s\n", err.Code)
    }
}

Real-World Example

// User registration schema with i18n support
registrationSchema := schema.Object().
    Property("username", schema.String().
        Pattern("^[a-zA-Z0-9_]+$").
        MinLength(3).
        MaxLength(20).
        Required(i18n.S("username is required"))).
    Property("email", schema.String().
        Email().
        Required(i18n.S("email address is required"))).
    Property("password", schema.String().
        MinLength(8, i18n.F("password must be at least %d characters", 8)).
        Pattern(".*[A-Z].*", i18n.S("password must contain uppercase")).
        Pattern(".*[0-9].*", i18n.S("password must contain number")).
        Required(i18n.S("password is required"))).
    Property("age", schema.Int().
        Min(13, i18n.F("must be at least %d years old", 13)).
        Max(120).
        Optional()).
    Property("terms", schema.Bool().
        Const(true, i18n.S("must accept terms and conditions")).
        Required()).
    AdditionalProperties(false)

// Validate registration data
data := map[string]interface{}{
    "username": "johndoe",
    "email": "john@example.com",
    "password": "SecurePass123",
    "age": 25,
    "terms": true,
}

result := registrationSchema.Parse(data, schema.DefaultValidationContext())
if result.Valid {
    fmt.Println("Registration data is valid!")
} else {
    for _, err := range result.Errors {
        fmt.Printf("Validation error: %s\n", err.Message)
    }
}

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Write tests for your changes
  4. Ensure all tests pass (go test ./...)
  5. Commit your changes (git commit -am 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

Testing

Run the test suite:

go test ./...

Run tests with coverage:

go test -cover ./...

License

This project is licensed under the MIT License - see the LICENSE file for details.

Related Projects

  • nyxstack/i18n - Internationalization support used by this library
  • nyxstack/validator - Struct tag based validation using this schema library. Enables validation through struct tags for seamless integration with Go structs.

Support

  • Create an issue for bug reports or feature requests
  • Check existing issues before creating new ones
  • Provide minimal reproducible examples for bugs

Made with ❤️ by the Nyx team

About

Fluent, type-safe schema validation and JSON Schema generation for Go. Supports strings, numbers, arrays, objects, unions, conditionals, nullable/optional fields, custom errors, formats, and full i18n error messaging. Build complex validation logic with a clean, chainable API and export standard JSON Schema.

Topics

Resources

License

Stars

Watchers

Forks

Languages