Practical JSON/YAML parsing with validation for Go.
Inspired by Python's Pydantic, gopantic provides type-safe parsing, coercion, and validation with idiomatic Go APIs.
Full Documentation: 1mb-dev.github.io/gopantic
go get github.com/1mb-dev/gopanticpackage main
import (
"fmt"
"log"
"github.com/1mb-dev/gopantic/pkg/model"
)
type User struct {
ID int `json:"id" validate:"required,min=1"`
Name string `json:"name" validate:"required,min=2"`
Email string `json:"email" validate:"required,email"`
Age int `json:"age" validate:"min=18,max=120"`
}
func main() {
raw := []byte(`{"id": "42", "name": "Alice", "email": "alice@example.com", "age": "28"}`)
user, err := model.ParseInto[User](raw)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", user) // {ID:42 Name:Alice Email:alice@example.com Age:28}
}- JSON/YAML parsing with automatic format detection
- Type coercion (
"123"→123,"true"→true) - Validation using struct tags (
validate:"required,email,min=5") - Standalone validation - use
Validate()independently of parsing - Cross-field validation (password confirmation, field comparisons)
- Built-in validators:
required,min,max,email,alpha,alphanum,length - Nested structs and arrays with full validation
- Time parsing (RFC3339, Unix timestamps, custom formats)
- Pointer support for optional fields (
*string,*int) - json.RawMessage support for flexible/deferred JSON parsing
- Caching support for repeated identical inputs (optional)
- Thread-safe concurrent parsing
- Zero dependencies (except optional YAML support)
- Generic API for type-safe parsing with compile-time guarantees
Works seamlessly with YAML - same API, automatic detection:
yamlData := []byte(`
id: 42
name: Alice
email: alice@example.com
age: 28
`)
user, err := model.ParseInto[User](yamlData) // Automatic YAML detectiongopantic seamlessly handles json.RawMessage fields for flexible metadata and JSONB database columns:
type Account struct {
ID string `json:"id" validate:"required"`
Name string `json:"name" validate:"required,min=2"`
MetadataRaw json.RawMessage `json:"metadata,omitempty"`
}
input := []byte(`{
"id": "acc_123",
"name": "John Doe",
"metadata": {"preferences": {"theme": "dark"}, "tags": ["vip"]}
}`)
account, err := model.ParseInto[Account](input)
// MetadataRaw preserves the raw JSON for later parsingUse Validate() to validate structs from any source (database, environment, etc.):
type Config struct {
Host string `json:"host" validate:"required"`
Port int `json:"port" validate:"min=1,max=65535"`
}
// Populate from environment or database
config := Config{
Host: os.Getenv("HOST"),
Port: 8080,
}
// Validate independently
if err := model.Validate(&config); err != nil {
log.Fatal(err)
}This enables flexible patterns:
// Pattern 1: Standard library unmarshal + gopantic validation
var req Request
json.Unmarshal(body, &req) // Handles json.RawMessage correctly
model.Validate(&req) // Apply gopantic validation rules
// Pattern 2: All-in-one (parsing + validation)
req, err := model.ParseInto[Request](body)type Product struct {
SKU string `json:"sku" validate:"required,length=8"`
Price float64 `json:"price" validate:"required,min=0.01"`
}
// Multiple validation errors are aggregated
product, err := model.ParseInto[Product](invalidData)
// Error: "multiple errors: validation error on field 'SKU': ...; validation error on field 'Price': ..."Built-in support for cross-field validation - compare fields against each other:
type UserRegistration struct {
Password string `json:"password" validate:"required,min=8"`
ConfirmPassword string `json:"confirm_password" validate:"required,password_match"`
Email string `json:"email" validate:"required,email"`
NotificationEmail string `json:"notification_email" validate:"email,email_different"`
}
// Register custom cross-field validators
model.RegisterGlobalCrossFieldFunc("password_match", func(fieldName string, fieldValue interface{}, structValue reflect.Value, params map[string]interface{}) error {
confirmPassword := fieldValue.(string)
password := structValue.FieldByName("Password").String()
if confirmPassword != password {
return model.NewValidationError(fieldName, fieldValue, "password_match", "passwords do not match")
}
return nil
})Optimized for production use - recent improvements deliver 40-65% faster parsing with 64% less memory:
| Metric | Standard Parsing | Cached Parsing |
|---|---|---|
| Speed vs stdlib JSON | 1.7x slower | 5.4x faster |
| Memory | 435 B/op | 112 B/op |
| Allocations | 14/op | 6/op |
Use cached parser for repeated identical inputs (configs, retries):
parser := model.NewCachedParser[User](nil)
user, _ := parser.Parse(data) // 5.4x faster for cache hitsNote: YAML is 4x slower than JSON due to parser complexity. Use JSON for performance-critical paths.
- Built-in validation - No separate validation step needed
- Type coercion - Handles
"123"→123automatically - Better errors - Structured error reporting with field paths
- YAML support - Automatic format detection
- Cross-field validation - Compare fields against each other
- Integrated parsing - Parse and validate in one step
- Type coercion - No manual string conversion needed
- Format agnostic - Works with JSON and YAML seamlessly
- Generics support - Type-safe with
ParseInto[T]() - Performance - Built-in caching for repeated operations
- Zero code generation - No build step or generated files
- Dynamic validation - Runtime validation rule changes
- Simpler workflow - Standard Go development process
- Faster iteration - No regeneration on struct changes
- Cross-field validation - Complex validation logic support
- Native Go structs - Use existing struct definitions
- Compile-time safety - Type checking at compile time
- Better performance - Direct struct mapping vs. schema validation
- IDE support - Full autocompletion and refactoring
- Integrated coercion - Automatic type conversion
A practical pre-commit hook is included that automatically:
- Checks for potential secrets in staged files
- Formats Go code with
go fmt - Runs
go vetfor static analysis - Performs fast linting with
golangci-lint - Runs tests if test files are modified
Install the hook:
make hooksFull documentation: 1mb-dev.github.io/gopantic
Quick links:
- Getting Started - Installation and basic usage
- API Reference - Complete API documentation
- Validation Guide - All validation options
- Migration Guide - Coming from other libraries
- Examples - Runnable code examples
Resources:
- Changelog - Version history
- Security Policy - Vulnerability reporting
MIT License - see LICENSE for details.