Table of contents
Part of nurago, a collection of independent Go packages for backend services.
import "github.com/tecnickcom/nurago/pkg/validator"
Package validator wraps https://github.com/go-playground/validator and adds custom validation rules, a template-based error translation engine, and a functional-options API.
How It Works
New creates a Validator using a variadic list of Option values:
- An upstream vt.Validate instance is created and held internally.
- Options register field-name tag aliases, custom validation functions, custom type functions, and error message templates on that instance.
Validator.ValidateStruct(or its context-aware twinValidator.ValidateStructCtx) runs the upstream validator and transforms anyvt.ValidationErrorsinto anerrors.Joinaggregate of typedErrorvalues, each carrying the failed tag, parameter, namespace, field name, kind, and the translated human-readable message.
Tag groups joined by “|” are iterated individually so each OR-branch failure produces an independent error.
Custom Rules
WithErrorTemplates maps a validation tag to a text/template string that
receives an Error value, giving access to the namespace, field name, tag,
parameter, kind, and actual value. ErrorTemplates returns a map covering the
built-in go-playground/validator tags plus the custom tags.
CustomValidationTags registers the custom validators:
- falseif: conditional negation combinator
- e164noplus: E.164 phone number without the leading ‘+’
- zipcode: US ZIP code (12345 or 12345-6789)
- usstate: two-letter US state code (including DC)
- usterritory: two-letter US territory code (AS, GU, MP, PR, VI)
- datetime_rfc3339: strict RFC-3339 datetime
- datetime_rfc3339_relaxed: RFC-3339 with space instead of ‘T’
WithFieldNameTag (commonly “json”) makes error namespaces use the serialized
field names rather than the Go struct field names. WithCustomValidationTags
and WithCustomTypeFunc register project-specific rules. Every failure is an
Error value.
Usage
v, err := validator.New(
validator.WithFieldNameTag("json"),
validator.WithCustomValidationTags(validator.CustomValidationTags()),
validator.WithErrorTemplates(validator.ErrorTemplates()),
)
if err != nil {
return err
}
type Address struct {
Phone string `json:"phone" validate:"required,e164noplus"`
ZIP string `json:"zip" validate:"required,zipcode"`
State string `json:"state" validate:"required,usstate"`
}
err = v.ValidateStruct(Address{Phone: "12345", ZIP: "bad", State: "XX"})
// err is an errors.Join aggregate containing one *Error per failed field,
// each with a message like:
// "phone must be a valid E.164 formatted phone number without the leading '+' symbol"
When To Use
- Request payloads are validated from struct tags.
- Error messages must be readable and templated rather than raw field paths.
- You need validation rules beyond the built-in set.
Example
// data structure to check
validObj := RootStruct{
BoolField: true,
SubStr: SubStruct{
URLField: "http://first.test.invalid",
IntField: 3,
},
SubStrPtr: &SubStruct{
URLField: "http://second.test.invalid",
IntField: 123,
},
StringField: "hello world",
NoNameField: "test",
}
// instantiate the validator object
v, err := validator.New(
validator.WithFieldNameTag(fieldTagName),
validator.WithCustomValidationTags(validator.CustomValidationTags()),
validator.WithErrorTemplates(validator.ErrorTemplates()),
)
if err != nil {
log.Fatal(err)
}
// check the data structure
err = v.ValidateStruct(validObj)
if err != nil {
log.Fatal(err)
}
fmt.Println("OK")
// Output:
// OK
Full source is in example_validator_test.go. More runnable examples are on pkg.go.dev.
Dependencies
Importing this package pulls 8 external modules:
github.com/gabriel-vasile/mimetypegithub.com/go-playground/localesgithub.com/go-playground/universal-translatorgithub.com/go-playground/validator/v10github.com/leodido/go-urngolang.org/x/cryptogolang.org/x/sysgolang.org/x/text