Validation¶
oapi-codegen generates Validate() methods for your types based on OpenAPI schema constraints.
This uses the go-playground/validator library under the hood.
Configuration Options¶
generate:
validation:
skip: false # Set to true to skip Validate() method generation
simple: false # Set to true to use simple validate.Struct() for all types
response: false # Set to true to generate Validate() for response types
skip¶
When true, no Validate() methods are generated. Use this if you don't need validation or want to implement your own.
simple¶
When true, all struct types use simple validate.Struct() validation instead of custom validation logic. This produces cleaner code but doesn't support advanced features like union type validation.
response¶
When true, generates Validate() methods for response types. Useful for contract testing to ensure API responses match the OpenAPI spec.
Supported OpenAPI Constraints¶
The following OpenAPI constraints are translated to validation tags:
| OpenAPI Constraint | Validation Tag | Applies To |
|---|---|---|
required |
required |
All types |
nullable: true |
omitempty |
All types |
minimum |
gte=N |
integers, numbers |
maximum |
lte=N |
integers, numbers |
exclusiveMinimum |
gt=N |
integers, numbers |
exclusiveMaximum |
lt=N |
integers, numbers |
minLength |
min=N |
strings, arrays |
maxLength |
max=N |
strings, arrays |
minItems |
min=N |
arrays |
maxItems |
max=N |
arrays |
enum |
custom switch | string, integer enums |
Generated Code Examples¶
Simple Struct Validation¶
For simple structs without unions or nested validators:
type DistanceBasedLocation struct {
Distance float32 `json:"distance" validate:"required,gte=0"`
}
func (d DistanceBasedLocation) Validate() error {
return runtime.ConvertValidatorError(typesValidator.Struct(d))
}
Enum Validation¶
Enum types get custom switch-based validation:
type Status string
const (
ACTIVE Status = "ACTIVE"
INACTIVE Status = "INACTIVE"
PENDING Status = "PENDING"
)
// Validate checks if the Status value is valid
func (s Status) Validate() error {
switch s {
case ACTIVE, INACTIVE, PENDING:
return nil
default:
return runtime.NewValidationErrorsFromString("Enum", fmt.Sprintf("must be a valid Status value, got: %v", s))
}
}
Complex Validation with Nested Types¶
For structs with nested types that implement Validator:
type Response struct {
Status Status `json:"status" validate:"required"`
// Unit A numeric unit for an indicator - includes empty string
Unit IndicatorUnit `json:"unit" validate:"required"`
NullableStatus *NullableStatus `json:"nullableStatus,omitempty"`
}
func (r Response) Validate() error {
var errors runtime.ValidationErrors
if v, ok := any(r.Status).(runtime.Validator); ok {
if err := v.Validate(); err != nil {
errors = errors.Append("Status", err)
}
}
if v, ok := any(r.Unit).(runtime.Validator); ok {
if err := v.Validate(); err != nil {
errors = errors.Append("Unit", err)
}
}
if r.NullableStatus != nil {
if v, ok := any(r.NullableStatus).(runtime.Validator); ok {
if err := v.Validate(); err != nil {
errors = errors.Append("NullableStatus", err)
}
}
}
if len(errors) == 0 {
return nil
}
return errors
}
Runtime Helpers¶
Validator Interface¶
All generated types with validation implement this interface:
type Validator interface {
Validate() error
}
ValidationErrors¶
A slice type that collects multiple validation errors with field paths:
var errors runtime.ValidationErrors
errors = errors.Append("FieldName", err)
ConvertValidatorError¶
Converts go-playground/validator errors to ValidationErrors:
return runtime.ConvertValidatorError(typesValidator.Struct(s))
Usage¶
Validating Request Bodies¶
func handleRequest(w http.ResponseWriter, r *http.Request) {
var body CreateUserRequest
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
if err := body.Validate(); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// Process valid request...
}
Contract Testing (Response Validation)¶
Enable response validation in config:
generate:
validation:
response: true
Then validate responses in tests:
func TestAPIResponse(t *testing.T) {
resp, err := client.GetUser(ctx, userID)
require.NoError(t, err)
// Validate response matches OpenAPI spec
if err := resp.Validate(); err != nil {
t.Errorf("Response validation failed: %v", err)
}
}