Files
dance-lessons-coach/adr/0011-validation-library-selection.md
Gabriel Radureau d3b6d190d1 feat: implement input validation for API v2
- Added go-playground/validator dependency

- Created pkg/validation/ package with custom validator wrapper

- Implemented request validation for v2 greet endpoint

- Added structured validation error responses

- Extended BDD tests to cover validation scenarios

- Updated AGENTS.md with v2 API documentation

- Created ADR 0011-validation-library-selection.md

- Simplified server handler creation code

- Updated CHANGELOG with implementation details
2026-04-04 21:08:13 +02:00

7.2 KiB

11. Validation Library Selection

Date: 2026-04-04 Status: Proposed Authors: AI Agent

Context

The DanceLessonsCoach project needs to add input validation for API requests, particularly for the new v2 API endpoints that accept JSON payloads. Currently, there is no structured validation in place, which could lead to invalid data being processed by the system.

Decision Drivers

  1. Maturity and Stability: Need a well-established library with proven track record
  2. Community Support: Active maintenance and community adoption
  3. Feature Completeness: Support for common validation scenarios (required fields, string lengths, numeric ranges, etc.)
  4. Performance: Minimal impact on request processing times
  5. Integration: Easy to integrate with existing Chi router and JSON handling
  6. Error Handling: Clear, actionable error messages for API consumers
  7. Extensibility: Ability to add custom validation rules

Considered Options

1. go-playground/validator (v10)

Overview: The most widely adopted validation library for Go, using struct tags for rule definition.

Pros:

  • Most mature and stable - Used in production by thousands of projects
  • Extensive built-in validators - Covers 90%+ of common validation needs
  • Large community - Active GitHub repository with frequent updates
  • Good documentation - Comprehensive examples and guides
  • Struct tag-based - Clean separation of validation rules from business logic
  • Custom validators - Support for adding project-specific validation rules
  • Cross-field validation - Can validate relationships between fields
  • JSON Schema generation - Can generate schemas from validation tags

Cons:

  • Reflection-based - Slightly slower than compile-time alternatives
  • Tag syntax - Can become verbose for complex validations
  • Error messages - Requires some customization for API-friendly errors

2. ozzo-validation

Overview: Configurable and extensible data validation using code-based rules.

Pros:

  • Code-based validation - Rules defined in Go code rather than tags
  • Customizable errors - Better control over error message formatting
  • Extensible - Easy to add new validation rules
  • Good performance - Faster than reflection-based validators

Cons:

  • Less mature - Smaller community than go-playground/validator
  • More verbose - Requires more code for common validations
  • Learning curve - Different approach than tag-based validation

3. Valgo

Overview: Type-safe, expressive, and extensible validator library.

Pros:

  • Type-safe - Compile-time type checking
  • Modern API - Clean, expressive syntax
  • Good performance - Type-safe approach can be faster
  • Extensible - Easy to add custom validators

Cons:

  • Newer library - Less battle-tested than go-playground/validator
  • Smaller community - Fewer resources and examples available
  • Breaking changes - Still evolving API

4. govalid

Overview: Compile-time validation library that generates validation code.

Pros:

  • Compile-time generation - Up to 45x faster than reflection-based
  • No reflection overhead - Better performance in hot paths
  • Type-safe - Compile-time checking

Cons:

  • Build complexity - Requires code generation step
  • Less flexible - Harder to add runtime validation rules
  • Smaller ecosystem - Fewer built-in validators

Decision Outcome

Chosen option: go-playground/validator (v10)

Rationale:

  1. Proven Track Record: Used successfully in countless production Go applications
  2. Community Support: Large ecosystem, active maintenance, and extensive documentation
  3. Feature Completeness: Covers all our current and anticipated validation needs
  4. Integration: Works seamlessly with our existing struct-based JSON handling
  5. Performance: While not the fastest, the performance impact is negligible for our use case
  6. Error Handling: Can be customized to provide API-friendly error messages
  7. Extensibility: Supports custom validators for project-specific needs

Implementation Plan

Phase 1: Integration Setup

  1. Add github.com/go-playground/validator/v10 dependency
  2. Create validation utility package in pkg/validation/
  3. Set up validator instance with custom error handling
  4. Add common validation tags and error message mappings

Phase 2: API v2 Validation

  1. Add validation to greetRequest struct in api_v2.go
  2. Implement request validation middleware
  3. Create custom error responses for validation failures
  4. Add comprehensive validation tests

Phase 3: Extend to Other Endpoints

  1. Apply validation to existing v1 endpoints (optional)
  2. Add validation to health/readiness endpoints (if needed)
  3. Create validation documentation for API consumers

Phase 4: Advanced Features

  1. Add custom validators for business rules
  2. Implement internationalized error messages
  3. Add validation performance monitoring

Validation Strategy

Request Validation Pattern

// Define validated struct
type GreetRequest struct {
    Name string `json:"name" validate:"required,min=1,max=100"`
}

// Validate in handler
func (h *apiV2GreetHandler) handleGreetPost(w http.ResponseWriter, r *http.Request) {
    var req GreetRequest
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        // Handle JSON decode error
        return
    }
    
    if err := validator.Validate(req); err != nil {
        // Return validation error response
        return
    }
    
    // Process valid request
    message := h.greeter.GreetV2(r.Context(), req.Name)
    h.writeJSONResponse(w, message)
}

Error Response Format

{
    "error": "validation_failed",
    "message": "Invalid request data",
    "details": [
        {
            "field": "name",
            "error": "required",
            "message": "Name is required"
        }
    ]
}

Migration Path

  1. Initial Integration: Add validator to v2 endpoints only
  2. Testing: Validate performance and error handling
  3. Documentation: Update API docs with validation requirements
  4. Gradual Rollout: Apply to other endpoints as needed
  5. Monitoring: Track validation failures and adjust rules

Future Considerations

  • Performance Optimization: If validation becomes bottleneck, consider compile-time alternatives
  • Schema Generation: Generate OpenAPI schemas from validation tags
  • Internationalization: Support multiple languages for error messages
  • Rule Management: Externalize validation rules for dynamic configuration

References

Changelog Entry

### 2026-04-04 - Validation Library Selection
- ✅ Selected go-playground/validator for input validation
- ✅ Created ADR 0011-validation-library-selection.md
- ✅ Planned integration strategy for API validation
- ✅ Designed error response format for validation failures