3 <img align="right" src="https://raw.githubusercontent.com/go-playground/validator/v8/logo.png">[![Join the chat at https://gitter.im/bluesuncorp/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4 ![Project status](https://img.shields.io/badge/version-8.18.2-green.svg)
5 [![Build Status](https://semaphoreci.com/api/v1/projects/ec20115f-ef1b-4c7d-9393-cc76aba74eb4/530054/badge.svg)](https://semaphoreci.com/joeybloggs/validator)
6 [![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=v8&service=github)](https://coveralls.io/github/go-playground/validator?branch=v8)
7 [![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator)
8 [![GoDoc](https://godoc.org/gopkg.in/go-playground/validator.v8?status.svg)](https://godoc.org/gopkg.in/go-playground/validator.v8)
9 ![License](https://img.shields.io/dub/l/vibe-d.svg)
11 Package validator implements value validations for structs and individual fields based on tags.
13 It has the following **unique** features:
15 - Cross Field and Cross Struct validations by using validation tags or custom validators.
16 - Slice, Array and Map diving, which allows any or all levels of a multidimensional field to be validated.
17 - Handles type interface by determining it's underlying type prior to validation.
18 - Handles custom field types such as sql driver Valuer see [Valuer](https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29)
19 - Alias validation tags, which allows for mapping of several validations to a single tag for easier defining of validations on structs
20 - Extraction of custom defined Field Name e.g. can specify to extract the JSON name while validating and have it available in the resulting FieldError
27 go get gopkg.in/go-playground/validator.v8
31 go get -u gopkg.in/go-playground/validator.v8
33 Then import the validator package into your own code.
35 import "gopkg.in/go-playground/validator.v8"
40 Validation functions return type error
42 They return type error to avoid the issue discussed in the following, where err is always != nil:
44 * http://stackoverflow.com/a/29138676/3158232
45 * https://github.com/go-playground/validator/issues/134
47 validator only returns nil or ValidationErrors as type error; so in you code all you need to do
48 is check if the error returned is not nil, and if it's not type cast it to type ValidationErrors
52 err := validate.Struct(mystruct)
53 validationErrors := err.(validator.ValidationErrors)
56 Usage and documentation
59 Please see http://godoc.org/gopkg.in/go-playground/validator.v8 for detailed usage docs.
63 Struct & Field validation
70 "gopkg.in/go-playground/validator.v8"
73 // User contains user information
75 FirstName string `validate:"required"`
76 LastName string `validate:"required"`
77 Age uint8 `validate:"gte=0,lte=130"`
78 Email string `validate:"required,email"`
79 FavouriteColor string `validate:"hexcolor|rgb|rgba"`
80 Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
83 // Address houses a users address information
85 Street string `validate:"required"`
86 City string `validate:"required"`
87 Planet string `validate:"required"`
88 Phone string `validate:"required"`
91 var validate *validator.Validate
95 config := &validator.Config{TagName: "validate"}
97 validate = validator.New(config)
103 func validateStruct() {
106 Street: "Eavesdown Docks",
115 Email: "Badger.Smith@gmail.com",
116 FavouriteColor: "#000",
117 Addresses: []*Address{address},
120 // returns nil or ValidationErrors ( map[string]*FieldError )
121 errs := validate.Struct(user)
125 fmt.Println(errs) // output: Key: "User.Age" Error:Field validation for "Age" failed on the "lte" tag
126 // Key: "User.Addresses[0].City" Error:Field validation for "City" failed on the "required" tag
127 err := errs.(validator.ValidationErrors)["User.Addresses[0].City"]
128 fmt.Println(err.Field) // output: City
129 fmt.Println(err.Tag) // output: required
130 fmt.Println(err.Kind) // output: string
131 fmt.Println(err.Type) // output: string
132 fmt.Println(err.Param) // output:
133 fmt.Println(err.Value) // output:
135 // from here you can create your own error messages in whatever language you wish
139 // save user to database
142 func validateField() {
143 myEmail := "joeybloggs.gmail.com"
145 errs := validate.Field(myEmail, "required,email")
148 fmt.Println(errs) // output: Key: "" Error:Field validation for "" failed on the "email" tag
162 "database/sql/driver"
166 "gopkg.in/go-playground/validator.v8"
169 // DbBackedUser User struct
170 type DbBackedUser struct {
171 Name sql.NullString `validate:"required"`
172 Age sql.NullInt64 `validate:"required"`
177 config := &validator.Config{TagName: "validate"}
179 validate := validator.New(config)
181 // register all sql.Null* types to use the ValidateValuer CustomTypeFunc
182 validate.RegisterCustomTypeFunc(ValidateValuer, sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})
184 x := DbBackedUser{Name: sql.NullString{String: "", Valid: true}, Age: sql.NullInt64{Int64: 0, Valid: false}}
185 errs := validate.Struct(x)
187 if len(errs.(validator.ValidationErrors)) > 0 {
188 fmt.Printf("Errs:\n%+v\n", errs)
192 // ValidateValuer implements validator.CustomTypeFunc
193 func ValidateValuer(field reflect.Value) interface{} {
194 if valuer, ok := field.Interface().(driver.Valuer); ok {
195 val, err := valuer.Value()
199 // handle the error how you want
205 Struct Level Validation
213 "gopkg.in/go-playground/validator.v8"
216 // User contains user information
218 FirstName string `json:"fname"`
219 LastName string `json:"lname"`
220 Age uint8 `validate:"gte=0,lte=130"`
221 Email string `validate:"required,email"`
222 FavouriteColor string `validate:"hexcolor|rgb|rgba"`
223 Addresses []*Address `validate:"required,dive,required"` // a person can have a home and cottage...
226 // Address houses a users address information
227 type Address struct {
228 Street string `validate:"required"`
229 City string `validate:"required"`
230 Planet string `validate:"required"`
231 Phone string `validate:"required"`
234 var validate *validator.Validate
238 config := &validator.Config{TagName: "validate"}
240 validate = validator.New(config)
241 validate.RegisterStructValidation(UserStructLevelValidation, User{})
246 // UserStructLevelValidation contains custom struct level validations that don't always
247 // make sense at the field validation level. For Example this function validates that either
248 // FirstName or LastName exist; could have done that with a custom field validation but then
249 // would have had to add it to both fields duplicating the logic + overhead, this way it's
250 // only validated once.
252 // NOTE: you may ask why wouldn't I just do this outside of validator, because doing this way
253 // hooks right into validator and you can combine with validation tags and still have a
254 // common error output format.
255 func UserStructLevelValidation(v *validator.Validate, structLevel *validator.StructLevel) {
257 user := structLevel.CurrentStruct.Interface().(User)
259 if len(user.FirstName) == 0 && len(user.LastName) == 0 {
260 structLevel.ReportError(reflect.ValueOf(user.FirstName), "FirstName", "fname", "fnameorlname")
261 structLevel.ReportError(reflect.ValueOf(user.LastName), "LastName", "lname", "fnameorlname")
264 // plus can to more, even with different tag than "fnameorlname"
267 func validateStruct() {
270 Street: "Eavesdown Docks",
280 Email: "Badger.Smith@gmail.com",
281 FavouriteColor: "#000",
282 Addresses: []*Address{address},
285 // returns nil or ValidationErrors ( map[string]*FieldError )
286 errs := validate.Struct(user)
290 fmt.Println(errs) // output: Key: 'User.LastName' Error:Field validation for 'LastName' failed on the 'fnameorlname' tag
291 // Key: 'User.FirstName' Error:Field validation for 'FirstName' failed on the 'fnameorlname' tag
292 err := errs.(validator.ValidationErrors)["User.FirstName"]
293 fmt.Println(err.Field) // output: FirstName
294 fmt.Println(err.Tag) // output: fnameorlname
295 fmt.Println(err.Kind) // output: string
296 fmt.Println(err.Type) // output: string
297 fmt.Println(err.Param) // output:
298 fmt.Println(err.Value) // output:
300 // from here you can create your own error messages in whatever language you wish
304 // save user to database
310 ###### Run on MacBook Pro (Retina, 15-inch, Late 2013) 2.6 GHz Intel Core i7 16 GB 1600 MHz DDR3 using Go version go1.5.3 darwin/amd64
313 BenchmarkFieldSuccess-8 20000000 118 ns/op 0 B/op 0 allocs/op
314 BenchmarkFieldFailure-8 2000000 758 ns/op 432 B/op 4 allocs/op
315 BenchmarkFieldDiveSuccess-8 500000 2471 ns/op 464 B/op 28 allocs/op
316 BenchmarkFieldDiveFailure-8 500000 3172 ns/op 896 B/op 32 allocs/op
317 BenchmarkFieldCustomTypeSuccess-8 5000000 300 ns/op 32 B/op 2 allocs/op
318 BenchmarkFieldCustomTypeFailure-8 2000000 775 ns/op 432 B/op 4 allocs/op
319 BenchmarkFieldOrTagSuccess-8 1000000 1122 ns/op 4 B/op 1 allocs/op
320 BenchmarkFieldOrTagFailure-8 1000000 1167 ns/op 448 B/op 6 allocs/op
321 BenchmarkStructLevelValidationSuccess-8 3000000 548 ns/op 160 B/op 5 allocs/op
322 BenchmarkStructLevelValidationFailure-8 3000000 558 ns/op 160 B/op 5 allocs/op
323 BenchmarkStructSimpleCustomTypeSuccess-8 2000000 623 ns/op 36 B/op 3 allocs/op
324 BenchmarkStructSimpleCustomTypeFailure-8 1000000 1381 ns/op 640 B/op 9 allocs/op
325 BenchmarkStructPartialSuccess-8 1000000 1036 ns/op 272 B/op 9 allocs/op
326 BenchmarkStructPartialFailure-8 1000000 1734 ns/op 730 B/op 14 allocs/op
327 BenchmarkStructExceptSuccess-8 2000000 888 ns/op 250 B/op 7 allocs/op
328 BenchmarkStructExceptFailure-8 1000000 1036 ns/op 272 B/op 9 allocs/op
329 BenchmarkStructSimpleCrossFieldSuccess-8 2000000 773 ns/op 80 B/op 4 allocs/op
330 BenchmarkStructSimpleCrossFieldFailure-8 1000000 1487 ns/op 536 B/op 9 allocs/op
331 BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 1000000 1261 ns/op 112 B/op 7 allocs/op
332 BenchmarkStructSimpleCrossStructCrossFieldFailure-8 1000000 2055 ns/op 576 B/op 12 allocs/op
333 BenchmarkStructSimpleSuccess-8 3000000 519 ns/op 4 B/op 1 allocs/op
334 BenchmarkStructSimpleFailure-8 1000000 1429 ns/op 640 B/op 9 allocs/op
335 BenchmarkStructSimpleSuccessParallel-8 10000000 146 ns/op 4 B/op 1 allocs/op
336 BenchmarkStructSimpleFailureParallel-8 2000000 551 ns/op 640 B/op 9 allocs/op
337 BenchmarkStructComplexSuccess-8 500000 3269 ns/op 244 B/op 15 allocs/op
338 BenchmarkStructComplexFailure-8 200000 8436 ns/op 3609 B/op 60 allocs/op
339 BenchmarkStructComplexSuccessParallel-8 1000000 1024 ns/op 244 B/op 15 allocs/op
340 BenchmarkStructComplexFailureParallel-8 500000 3536 ns/op 3609 B/op 60 allocs/op
343 Complimentary Software
344 ----------------------
346 Here is a list of software that compliments using this library either pre or post validation.
348 * [form](https://github.com/go-playground/form) - Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support.
349 * [Conform](https://github.com/leebenson/conform) - Trims, sanitizes & scrubs data based on struct tags.
354 There will always be a development branch for each version i.e. `v1-development`. In order to contribute,
355 please make your pull requests against those branches.
357 If the changes being proposed or requested are breaking changes, please create an issue, for discussion
358 or create a pull request against the highest development branch for example this package has a
359 v1 and v1-development branch however, there will also be a v2-development branch even though v2 doesn't exist yet.
361 I strongly encourage everyone whom creates a custom validation function to contribute them and
362 help make this package even better.
366 Distributed under MIT License, please see license file in code for more details.