Skip to main content

Validation

VEF uses go-playground/validator as the base validation engine and layers framework-specific behavior on top:

  • translated error messages
  • label / label_i18n support
  • custom validation rules
  • null-type support for framework null wrappers

Validation Entry Point

Typed params and typed meta structs are validated automatically after decoding. The framework calls:

validator.Validate(value)

That means handler parameters using typed request structs get validation by default without manual calls inside the handler.

Standard Validator Tags

VEF inherits the standard go-playground/validator tag set. Common examples include:

TagMeaningExample
requiredfield must be present and non-zerovalidate:"required"
emailfield must be a valid emailvalidate:"required,email"
minnumeric or length lower boundvalidate:"min=1"
maxnumeric or length upper boundvalidate:"max=32"
oneoffield must match one of several valuesvalidate:"oneof=admin user guest"
lenexact lengthvalidate:"len=32"
omitemptyskip later validations when emptyvalidate:"omitempty,email"
divevalidate each slice or map itemvalidate:"required,dive"

VEF does not redefine those upstream rules; it adds framework-specific rules on top of them.

Label Resolution

Validation errors use field labels instead of raw Go field names when possible.

Resolution order:

SourceEffect
label:"..."uses the explicit label text directly
label_i18n:"..."resolves the label through i18n first, then falls back to the field name
neither tag presentuses the Go field name

Example:

type UserParams struct {
api.P

Username string `json:"username" validate:"required" label:"Username"`
Phone string `json:"phone" validate:"phone_number" label_i18n:"user_phone"`
}

Built-In Custom Rules

VEF currently ships these custom validation rules:

Rule tagExpected field typeMeaningExample
phone_numberstringvalidates a Mainland China mobile numbervalidate:"phone_number"
dec_min=<value>decimal.Decimaldecimal value must be greater than or equal to the thresholdvalidate:"dec_min=0"
dec_max=<value>decimal.Decimaldecimal value must be less than or equal to the thresholdvalidate:"dec_max=999.99"
alphanum_usstringletters, numbers, underscore onlyvalidate:"alphanum_us"
alphanum_us_slashstringletters, numbers, underscore, slash onlyvalidate:"alphanum_us_slash"
alphanum_us_dotstringletters, numbers, underscore, dot onlyvalidate:"alphanum_us_dot"

phone_number

RuleDetails
accepted values1[3-9]\\d{9}
intended usemobile phone input validation
common error shapetranslated message meaning “format is invalid”

dec_min / dec_max

RuleDetails
accepted field typedecimal.Decimal
parameter formatdecimal string such as 10.5
behaviorcompares the field value against the parsed decimal threshold

alphanum_us

RuleAllowed characters
alphanum_usletters, digits, _
alphanum_us_slashletters, digits, _, /
alphanum_us_dotletters, digits, _, .

Typical uses:

RuleTypical use
alphanum_usaction names, identifiers, simple codes
alphanum_us_slashRPC resource names or slash-separated identifiers
alphanum_us_dotfile names, module names, dotted identifiers

Supported Null Types

VEF registers custom type functions so that these null wrappers participate correctly in validation:

Supported null type
null.String
null.Int
null.Int16
null.Int32
null.Float
null.Bool
null.Byte
null.DateTime
null.Date
null.Time
null.Decimal

Practical effect:

  • when a null wrapper is valid, validation runs against the wrapped value
  • when it is invalid, the value is treated as nil

Error Behavior

Validation returns the first translated validation error as a framework result.Error.

CaseOutcome
validation succeedshandler continues normally
one or more validation rules failframework returns a bad-request style error
non-validation error occurs during validationframework wraps it as a bad-request style error

HTTP behavior:

PropertyValue
business coderesult.ErrCodeBadRequest
HTTP status400 Bad Request

Registering Additional Custom Rules

Applications can register their own rules through validator.RegisterValidationRules(...).

A rule is defined by validator.ValidationRule, which includes:

FieldPurpose
RuleTagvalidator tag name
ErrMessageTemplatefallback translated message template
ErrMessageI18nKeyi18n message key
Validateactual validation function
ParseParamparameter extraction for error message placeholders
CallValidationEvenIfNullwhether the rule should run on null values

Practical Patterns

Simple required fields

type UserParams struct {
api.P

Username string `json:"username" validate:"required,alphanum,max=32" label:"Username"`
Email string `json:"email" validate:"omitempty,email,max=128" label:"Email"`
}

Decimal range validation

type PriceParams struct {
api.P

Amount decimal.Decimal `json:"amount" validate:"dec_min=0,dec_max=999999.99" label:"Amount"`
}

Null wrapper validation

type UserParams struct {
api.P

Phone null.String `json:"phone" validate:"omitempty,phone_number" label:"Phone"`
}

Practical Advice

  • put validation rules on typed params and meta structs, not inside handlers
  • use label or label_i18n so error messages remain user-facing
  • prefer framework custom rules when they match your contract
  • keep custom rules narrow and domain-specific
  • if the field type is a framework null wrapper, rely on built-in null-type support instead of manual unwrapping

Next Step

Read Parameters And Metadata to see where validation is triggered in request decoding.