validate
Go package for data validation and filtering. support validate Map, Struct, Request(Form, JSON, url.Values, Uploaded Files) data and more features
About validate
This large README is shown as a plain-text preview. Read the full README at the source
# Validate
[](https://github.com/gookit/validate)
[](https://pkg.go.dev/github.com/gookit/validate)

[](https://coveralls.io/github/gookit/validate?branch=master)
[](https://goreportcard.com/report/github.com/gookit/validate)
[](https://github.com/gookit/validate/actions)
`validate` is a generic Go data validate and filter tool library.
> **[中文说明](README.zh-CN.md)**
- Support quick validate `Map`, `Struct`, `Request`(`Form`, `JSON`, `url.Values`, `UploadedFile`) data
- Validating `http.Request` automatically collects data based on the request `Content-Type` value
- Supports checking each child value in a slice. eg: `v.StringRule("tags.*", "required|string")`
- Support filter/sanitize/convert data before validate
- Support add custom filter/validator func
- Support scene settings, verify different fields in different scenes
- Support custom error messages, field translates.
- Can use `message`, `label` tags in struct
- Customizable i18n aware error messages, built in `en`, `zh-CN`, `zh-TW`
- Built-in common data type filter/converter. see [Built In Filters](#built-in-filters)
- Many commonly used validators have been built in(**> 70**), see [Built In Validators](#built-in-validators)
- Can use `validate` in any frameworks, such as Gin, Echo, Chi and more
- Supports direct use of rules to validate value. eg: `validate.Val("[email protected]", "required|email")`
## Go Doc
- [Godoc for github](https://pkg.go.dev/github.com/gookit/validate/v2)
> **v2.0**: the module path is now `github.com/gookit/validate/v2` (requires Go 1.21+).
> See the [upgrade guide](docs/UPGRADE-v2.md) for migrating from v1.x.
>
> **Performance**: see [Benchmark comparison](docs/benchmark-v1-to-v2.md) for the v1.5.7 → v1.6.0 → v2.0.0 benchmark results.
Install:
```bash
go get github.com/gookit/validate/v2
```
## Validate Struct
Use the `validate` tag of the structure, you can quickly config a structure.
### Config the struct use tags
Field translations and error messages for structs can be quickly configured using the `message` and `label` tags.
- Support configuration field mapping through structure tag, read the value of `json` tag by default
- Support configuration error message via structure's `message` tag
- Support configuration field translation via structure's `label` tag
```go
package main
import (
"fmt"
"time"
"github.com/gookit/validate/v2"
)
// UserForm struct
type UserForm struct {
Name string `validate:"required|min_len:7" message:"required:{field} is required" label:"User Name"`
Email string `validate:"email" message:"email is invalid" label:"User Email"`
Age int `validate:"required|int|min:1|max:99" message:"int:age must int|min:age min value is 1"`
CreateAt int `validate:"min:1"`
Safe int `validate:"-"`
UpdateAt time.Time `validate:"required" message:"update time is required"`
Code string `validate:"customValidator"`
// ExtInfo nested struct
ExtInfo struct{
Homepage string `validate:"required" label:"Home Page"`
CityName string
} `validate:"required" label:"Home Page"`
}
// CustomValidator custom validator in the source struct.
func (f UserForm) CustomValidator(val string) bool {
return len(val) == 4
}
```
### Config validate use struct methods
`validate` provides extended functionality:
The struct can implement three interfaces methods, which is convenient to do some customization:
- `ConfigValidation(v *Validation)` will be called after the validator instance is created
- `Messages() map[string]string` can customize the validator error message
- `Translates() map[string]string` can customize field translation
```go
package main
import (
"fmt"
"time"
"github.com/gookit/validate/v2"
)
// UserForm struct
type UserForm struct {
Name string `validate:"required|min_len:7"`
Email string `validate:"email"`
Age int `validate:"required|int|min:1|max:99"`
CreateAt int `validate:"min:1"`
Safe int `validate:"-"`
UpdateAt time.Time `validate:"required"`
Code string `validate:"customValidator"`
// ExtInfo nested struct
ExtInfo struct{
Homepage string `validate:"required"`
CityName string
} `validate:"required"`
}
// CustomValidator custom validator in the source struct.
func (f UserForm) CustomValidator(val string) bool {
return len(val) == 4
}
// ConfigValidation config the Validation
// eg:
// - define validate scenes
func (f UserForm) ConfigValidation(v *validate.Validation) {
v.WithScenes(validate.SValues{
"add": []string{"ExtInfo.Homepage", "Name", "Code"},
"update": []string{"ExtInfo.CityName", "Name"},
})
}
// Messages you can custom validator error messages.
func (f UserForm) Messages() map[string]string {
return validate.MS{
"required": "oh! the {field} is required",
"email": "email is invalid",
"Name.required": "message for special field",
"Age.int": "age must int",
"Age.min": "age min value is 1",
}
}
// Translates you can custom field translates.
func (f UserForm) Translates() map[string]string {
return validate.MS{
"Name": "User Name",
"Email": "User Email",
"ExtInfo.Homepage": "Home Page",
}
}
```
### Create and validating
Can use `validate.Struct(ptr)` quick create a validation instance. then call `v.Validate()` for validating.
```go
package main
import (
"fmt"
"github.com/gookit/validate/v2"
)
func main() {
u := &UserForm{
Name: "inhere",
}
v := validate.Struct(u)
// v := validate.New(u)
if v.Validate() { // validate ok
// do something ...
} else {
fmt.Println(v.Errors) // all error messages
fmt.Println(v.Errors.One()) // returns a random error message text
fmt.Println(v.Errors.OneError()) // returns a random error
fmt.Println(v.Errors.Field("Name")) // returns error messages of the field
}
}
```
### Sub-struct (nested) validation
By default (`CheckSubOnParentMarked=true`), a **named** sub-struct field
(`struct` / `*struct` / slice-of-struct / map-of-struct) is descended into to
collect its inner rules **only when it carries a `validate` tag**. The tag
**value may be empty** — `validate:""` is enough to mark the field. A named field
with **no** `validate` tag at all is **not** descended into. This is the Java
`@Valid` style of on-demand cascade, avoiding pointless recursion through the
whole struct tree.
**Anonymous embedded structs are exempt**: `type Bar struct { Foo }` (the field
is promoted and is part of the parent) **always cascades**, no tag needed. Only
**named** nested fields need the marker.
```go
type Address struct {
City string `validate:"required"`
}
type User struct {
Name string `validate:"required"`
Home Address `validate:"required"` // has tag -> descend, validates Home.City
Work Address `validate:""` // empty tag is also a marker -> descend
Temp Address // no tag -> not descended, Temp.City ignored
}
```
To restore v1's unconditional cascade behaviour globally:
```go
validate.Config(func(o *validate.GlobalOption) {
o.CheckSubOnParentMarked = false
})
```
> See the [upgrade guide](docs/UPGRADE-v2.md) for more on this behaviour change.
## Validate Map
You can also validate a MAP data directly.
```go
package main
import (
"fmt"
"github.com/gookit/validate/v2"
)
func main() {
m := map[string]any{
"name": "inhere",
"age": 100,
"oldSt": 1,
"newSt": 2,
"email": "[email protected]",
"tags": []string{"go", "php", "java"},
}
v := validate.Map(m)
// v := validate.New(m)
v.AddRule("name", "required")
v.AddRule("name", "minLen", 7)
v.AddRule("age", "max", 99)
v.AddRule("age", "min", 1)
v.AddRule("email", "email")
// can also
v.StringRule("age", "required|int|min:1|max:99")
v.StringRule("name", "required|minLen:7")
v.StringRule("tags", "required|slice|minlen:1")
// feat: support check sub-item in slice
v.StringRule("tags.*", "required|string|min_len:7")
// v.WithScenes(map[string]string{
// "create": []string{"name", "email"},
// "update": []string{"name"},
// })
r := v.ValidateR() // returns a *ValidResult, decoupled from v
if r.IsOK() { // validate ok
safeData := r.SafeData()
// do something ...
} else {
fmt.Println(r.Errors) // all error messages
fmt.Println(r.Errors.One()) // returns a random error message text
}
}
```
> Tip: for struct validation, prefer the top-level `validate.Check(&u)` — it is
> stateless and pooled internally, and returns the same `*ValidResult`.
## Validate Request
If it is an HTTP request, you can quickly validate the data and pass the verification.
Then bind the secure data to the structure.
```go
package main
import (
"fmt"
"net/http"
"time"
"github.com/gookit/validate/v2"
)
// UserForm struct
type UserForm struct {
Name string
Email string
Age int
CreateAt int
Safe int
UpdateAt time.Time
Code string
}
func main() {
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
data, err := validate.FromRequest(r)
if err != nil {
panic(err)
}
v := data.Create()
// setting rules
v.FilterRule("age", "int") // convert value to int
v.AddRule("name", "required")
v.AddRule("name", "minLen", 7)
v.AddRule("age", "max", 99)
v.StringRule("code", `required|regex:\d{4,6}`)
vr := v.ValidateR()
if vr.IsOK() { // validate ok
// safeData := vr.SafeData()
userForm := &UserForm{}
vr.BindSafeData(userForm)
// do something ...
fmt.Println(userForm.Name)
} else {
fmt.Println(vr.Errors) // all error messages
fmt.Println(vr.Errors.One()) // returns a random error message text
}
})
http.ListenAndServe(":8090", handler)
}
```
## Quick Method
Quick validate a struct (pooled internally, no manual lifecycle):
- `Check(structPtr any, scene ...string) *ValidResult` — recommended default for struct validation. Stateless from the caller's side, internally pooled. Returns a `*ValidResult` carrying the cleaned/safe data and bind helpers.
- `CheckErr(structPtr any, scene ...string) error` — **opt-in FAST entry** for "only need ok/err, no safe data / no binding". Pooled like `Check` but it **skips collecting safeData/filteredData** and does not build a `*ValidResult`, so it reaches fewer allocations (struct-valid: **0 allocs** vs `Check` 6, via RV-native end-to-end deboxing). Returns `nil` on pass, otherwise the first error.
```go
// fast pass/fail (e.g. middleware reject) — no cleaned data needed
if err := validate.CheckErr(&u); err != nil {
return err
}
// need the cleaned data or BindStruct? use Check / ValidateR instead
r := validate.Check(&u)
if r.Fail() {
return r.Err()
}
r.BindSafeData(&out)
```
> `CheckErr` is struct-only. For map data or programmatic rules, build a `Validation` (`New`/`Map` + `StringRule...`) and call `ValidateErr()`.
Quick create `Validation` instance.
- `New(data any, scene ...string) *Validation`
- `Request(r *http.Request) *Validation`
- `JSON(s string, scene ...string) *Validation`
- `Struct(s any, scene ...string) *Validation`
- `Map(m map[string]any, scene ...string) *Validation`
Quick create `DataFace` instance.
- `FromMap(m map[string]any) *MapData`
- `FromStruct(s any) (*StructData, error)`
- `FromJSON(s string) (*MapData, error)`
- `FromJSONBytes(bs []byte) (*MapData, error)`
- `FromURLValues(values url.Values) *FormData`
- `FromRequest(r *http.Request, maxMemoryLimit ...int64) (DataFace, error)`
> Create `Validation` from `DataFace`
```go
d := FromMap(map[string]any{"key": "val"})
v := d.Validation()
```
### Methods In Validation
- `func (v *Validation) Validate(scene ...string) bool` Do validating and return is success.
- `func (v *Validation) ValidateE(scene ...string) Errors` Do validating and return error.
- `func (v *Validation) ValidateR(scene ...string) *ValidResult` Validate and return a `ValidResult` decoupled from the instance.
> **Since v2.0, `Validation` keeps only the pass/fail + error face.** The safe-data /
> bind methods (`SafeData()` / `Safe()` / `SafeVal()` / `Filtered()` / `FilteredData()` /
> `BindSafeData()` / `BindStruct()`) moved to the result object `ValidResult`. Get one via
> `validate.Check(&u)` (recommended for structs, pooled) or `v.ValidateR()` (map/builder),
> then call e.g. `r.SafeData()` / `r.BindStruct(ptr)`. For pass/fail only, use
> `validate.CheckErr(structPtr any, scene ...string) error` (fewest allocations).
## More Usage
### Validate Error
`v.Errors` is map data, top key is field name, value is `map[string]string`.
```go
// do validating
if v.Validate() {
return nil
}
// get errors
es := v.Errors
// check
es.Empty() // bool
// returns an random error, if no error returns nil
fmt.Println(v.Errors.OneError())
fmt.Println(v.Errors.ErrOrNil())
fmt.Println(v.Errors) // all error messages
fmt.Println(v.Errors.One()) // returns a random error message text
fmt.Println(v.Errors.Field("Name")) // returns error messages of the field
```
**Encode to JSON**:
- `StopOnError=true`(default), will only one error
```json
{
"field1": {
"required": "error msg0"
}
}
```
- if `StopOnError=false`, will get multi error
```json
{
"field1": {
"minLen": "error msg1",
"required": "error msg0"
},
"field2": {
"min": "error msg2"
}
}
```
### Global Option
You can adjust some processing logic of the validator by changing the global option settings.
```go
// GlobalOption settings for validate
type GlobalOption struct {
// FilterTag name in the struct tags.
//
// default: filter
FilterTag string
// ValidateTag in the struct tags.
//
// default: validate
ValidateTag string
// FieldTag the output field name in the struct tags.
// it as placeholder on error message.
//
// default: json
FieldTag string
// LabelTag the display name in the struct tags.
// use for define field translate name on error.
//
// default: label
LabelTag string
// MessageTag define error message for the field.
//
// default: message
MessageTag string
// StopOnError If true: An error occurs, it will cease to continue to verify
StopOnError bool
// SkipOnEmpty Skip check on field not exist or value is empty
SkipOnEmpty bool
// UpdateSource Whether to update source field value, useful for struct validate
UpdateSource bool
// CheckDefault Whether to validate the default value set by the user
CheckDefault bool
// CheckZero Whether validate the default zero value. (intX,uintX: 0, string: "")
CheckZero bool
// CheckSubOnParentMarked True: only collect sub-struct rule on current field has rule.
CheckSubOnParentMarked bool
// ValidatePrivateFields Whether to validate private fields or not, especially when inheriting other other structs.
//
// type foo struct {
// Field int `json:"field" validate:"required"`
// }
// type bar struct {
// foo // <-- validate this field
// Field2 int `json:"field2" validate:"required"`
// }
//
// default: false
ValidatePrivateFields bool
}
```
**Usage**:
```go
// change global opts
validate.Config(func(opt *validate.GlobalOption) {
opt.StopOnError = false
opt.SkipOnEmpty = false
})
```
### Validating Private (Unexported fields)
By default, private fields are skipped. It is not uncommon to find code such as the following
```go
type foo struct {
somefield int
}
type Bar struct {
foo
SomeOtherField string
}
```
In order to have `foo.somefield` validated, enable the behavior by setting `GlobalOption.ValidatePrivateFields` to `true`.
```go
validate.Config(func(opt *validate.GlobalOption) {
opt.ValidatePrivateFields = true
})
```
### Custom Error Messages
- Register language messages
```go
import "github.com/gookit/validate/v2/locales/zhcn"
// for all Validation.
// NOTICE: must be registered before on validate.New(), it only need call at once.
zhcn.RegisterGlobal()
// ... ...
v := validate.New()
// only for current Validation
zhcn.Register(v)
```
- Manual add global messages
```go
validate.AddGlobalMessages(map[string]string{
"minLength": "OO! {field} min length is %d",
})
```
- Add messages for current validation
```go
v := validate.New(map[string]any{
"name": "inhere",
})
v.StringRule("name", "required|string|minLen:7|maxLen:15")
v.AddMessages(map[string]string{
"minLength": "OO! {field} min length is %d",
"name.minLen": "OO! username min length is %d",
})
```
- Use struct tags: `message, label`
```go
type UserForm struct {
Name string `validate:"required|minLen:7" label:"User Name"`
Email string `validate:"email" message:"email is invalid" label:"User Email"`
}
```
- Use struct method `Messages()`
```go
// Messages you can custom validator error messages.
func (f UserForm) Messages() map[string]string {
return validate.MS{
"required": "oh! the {field} is required",
"Name.required": "message for special field",
}
}
```
### Add Custom Validator
`validate` supports adding custom validators, and supports adding `global validator` and `temporary validator`.
- **Global Validator** is globally valid and can be used everywhere
- **Temporary Validator** added to the current validation instance, only the current validation is available
- Add verification method to the structure. How to use please see the structure verification example above
> Note: The validator method must return a `bool` to indicate whether the validation was successful.
> The first parameter is the corresponding field value. If there are additional parameters, they will be appended automatically.
#### Add Global Validator
You can add one or more custom validators at once.
```go
validate.AddValidator("myCheck0", func(val any) bool {
// do validate val ...
return true
})
validate.AddValidators(validate.M{
"myCheck1": func(val any) bool {
// do validate val ...
return true
},
})
```
#### Add Temporary Validator
Again, you can add one or more custom validators at once.
```go
v := validate.Struct(u)
v.AddValidator("myFunc3", func(val any) bool {
// do validate val ...
return true
})
v.AddValidators(validate.M{
"myFunc4": func(val any) bool {
// do validate val ...
return true
},
})
```
### Add Custom Filter
`validate` can also support adding custom filters, and supports adding `global filter` and `temporary filter`.
- **Global Filter** is globally valid and can be used everywhere
- **Temporary Filter** added to the current validation instance, only the current validation is available
> TIP: for filter func, we allow functions with 1 result or 2 results where the second is an error.
#### Add Global Filter
You can add one or more custom validators at once.
```go
package main
import "github.com/gookit/validate/v2"
func init() {
validate.AddFilter("myToIntFilter0", func(val any) int {
// do filtering val ...
return 1
})
validate.AddFilters(validate.M{
"myToIntFilter1": func(val any) (int, error) {
// do filtering val ...
return 1, nil
},
})
}
```
#### Add Temporary Filter
Again, you can add one or more custom filters at once.
```go
package main
import "github.com/gookit/validate/v2"
func main() {
v := validate.New(&someStrcut{})
v.AddFilter("myToIntFilter0", func(val any) int {
// do filtering val ...
return 1
})
v.AddFilters(validate.M{
"myToIntFilter1": func(val any) (int, error) {
// do filtering val ...
return 1, nil
},
})
// use the added filter
v.FilterRule("field", "myToIntFilter0")
}
```
### Custom `required` validation
Allows a custom `required` validator to customize whether the validation is empty.Frequently Asked Questions
What is validate?
validate is a Validation library for the Go programming language. Go package for data validation and filtering. support validate Map, Struct, Request(Form, JSON, url.Values, Uploaded Files) data and more features
How many GitHub stars does validate have?
validate has 1,166 GitHub stars in the directory's latest synchronization.
How do I install validate?
Install validate with the Go module system using `go get gookit/validate`. Check the repository for the current installation instructions.
What category does validate belong to?
validate is listed under Validation, specifically Validation.