LogoPly
Features

Validation

Validate bound structs with go-playground/validator tags.

Validation

Ply validates structs with go-playground/validator. Use validate tags and call c.Validate, or let c.Bind bind and validate in one step.

type CreateUser struct {
	Name  string `json:"name" validate:"required,min=2,max=64"`
	Email string `json:"email" validate:"required,email"`
	Age   int    `json:"age" validate:"gte=0,lte=130"`
}

app.Post("/users", func(c *core.Context) {
	var input CreateUser
	if err := c.Bind(&input); err != nil {
		c.JSON(400, map[string]string{"error": err.Error()})
		return
	}
	c.JSON(201, input)
})

c.Bind selects the source from the content type, binds the values, then validates the result. Use c.Validate(&input) when you bind manually.

Field names in errors

Validation errors use the name from the first available tag in this order:

  1. json
  2. form
  3. query

If none is present, the Go field name is used. In the example above, an invalid email produces a field name of email, not Email.

Error type

c.Validate returns nil on success. On failure it returns *core.ValidationError:

type FieldError struct {
	Field string
	Tag   string
	Param string
	Value any
}

type ValidationError struct {
	Errors []FieldError
}

Use errors.As to format a response:

var verr *core.ValidationError
if errors.As(err, &verr) {
	out := make(map[string]string, len(verr.Errors))
	for _, field := range verr.Errors {
		out[field.Field] = field.Tag
	}
	c.JSON(422, out)
	return
}

ValidationError.Error() returns a compact string such as validation failed: email: required, age: lte.

Common tags

TagMeaning
requiredValue must not be the zero value
min, maxLength or numeric range
gte, lteGreater or less than or equal
emailEmail format
urlURL format
uuidUUID format
oneofOne of the listed values

The full tag list is in the validator documentation.

Nested structs

Validator traverses nested structs and their fields. Add validation tags to each level. For slices of structs, use dive when you need to validate each element.

Notes

  • Validation runs after binding. A parse error stops before validation.
  • A non-struct or nil target is rejected or skipped as documented by the validator.
  • Ply creates one validator instance for the process. Custom validator registration is not exposed through the public API.