OSDN Git Service

feat(warder): add warder backbone (#181)
[bytom/vapor.git] / vendor / gopkg.in / go-playground / validator.v8 / README.md
1 Package validator
2 ================
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)
10
11 Package validator implements value validations for structs and individual fields based on tags.
12
13 It has the following **unique** features:
14
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
21
22 Installation
23 ------------
24
25 Use go get.
26
27         go get gopkg.in/go-playground/validator.v8
28
29 or to update
30
31         go get -u gopkg.in/go-playground/validator.v8
32
33 Then import the validator package into your own code.
34
35         import "gopkg.in/go-playground/validator.v8"
36
37 Error Return Value
38 -------
39
40 Validation functions return type error
41
42 They return type error to avoid the issue discussed in the following, where err is always != nil:
43
44 * http://stackoverflow.com/a/29138676/3158232
45 * https://github.com/go-playground/validator/issues/134
46
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
49 like so:
50
51 ```go
52 err := validate.Struct(mystruct)
53 validationErrors := err.(validator.ValidationErrors)
54  ```
55
56 Usage and documentation
57 ------
58
59 Please see http://godoc.org/gopkg.in/go-playground/validator.v8 for detailed usage docs.
60
61 ##### Examples:
62
63 Struct & Field validation
64 ```go
65 package main
66
67 import (
68         "fmt"
69
70         "gopkg.in/go-playground/validator.v8"
71 )
72
73 // User contains user information
74 type User struct {
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...
81 }
82
83 // Address houses a users address information
84 type Address struct {
85         Street string `validate:"required"`
86         City   string `validate:"required"`
87         Planet string `validate:"required"`
88         Phone  string `validate:"required"`
89 }
90
91 var validate *validator.Validate
92
93 func main() {
94
95         config := &validator.Config{TagName: "validate"}
96
97         validate = validator.New(config)
98
99         validateStruct()
100         validateField()
101 }
102
103 func validateStruct() {
104
105         address := &Address{
106                 Street: "Eavesdown Docks",
107                 Planet: "Persphone",
108                 Phone:  "none",
109         }
110
111         user := &User{
112                 FirstName:      "Badger",
113                 LastName:       "Smith",
114                 Age:            135,
115                 Email:          "Badger.Smith@gmail.com",
116                 FavouriteColor: "#000",
117                 Addresses:      []*Address{address},
118         }
119
120         // returns nil or ValidationErrors ( map[string]*FieldError )
121         errs := validate.Struct(user)
122
123         if errs != nil {
124
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:
134
135                 // from here you can create your own error messages in whatever language you wish
136                 return
137         }
138
139         // save user to database
140 }
141
142 func validateField() {
143         myEmail := "joeybloggs.gmail.com"
144
145         errs := validate.Field(myEmail, "required,email")
146
147         if errs != nil {
148                 fmt.Println(errs) // output: Key: "" Error:Field validation for "" failed on the "email" tag
149                 return
150         }
151
152         // email ok, move on
153 }
154 ```
155
156 Custom Field Type
157 ```go
158 package main
159
160 import (
161         "database/sql"
162         "database/sql/driver"
163         "fmt"
164         "reflect"
165
166         "gopkg.in/go-playground/validator.v8"
167 )
168
169 // DbBackedUser User struct
170 type DbBackedUser struct {
171         Name sql.NullString `validate:"required"`
172         Age  sql.NullInt64  `validate:"required"`
173 }
174
175 func main() {
176
177         config := &validator.Config{TagName: "validate"}
178
179         validate := validator.New(config)
180
181         // register all sql.Null* types to use the ValidateValuer CustomTypeFunc
182         validate.RegisterCustomTypeFunc(ValidateValuer, sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})
183
184         x := DbBackedUser{Name: sql.NullString{String: "", Valid: true}, Age: sql.NullInt64{Int64: 0, Valid: false}}
185         errs := validate.Struct(x)
186
187         if len(errs.(validator.ValidationErrors)) > 0 {
188                 fmt.Printf("Errs:\n%+v\n", errs)
189         }
190 }
191
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()
196                 if err == nil {
197                         return val
198                 }
199                 // handle the error how you want
200         }
201         return nil
202 }
203 ```
204
205 Struct Level Validation
206 ```go
207 package main
208
209 import (
210         "fmt"
211         "reflect"
212
213         "gopkg.in/go-playground/validator.v8"
214 )
215
216 // User contains user information
217 type User struct {
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...
224 }
225
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"`
232 }
233
234 var validate *validator.Validate
235
236 func main() {
237
238         config := &validator.Config{TagName: "validate"}
239
240         validate = validator.New(config)
241         validate.RegisterStructValidation(UserStructLevelValidation, User{})
242
243         validateStruct()
244 }
245
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.
251 //
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) {
256
257         user := structLevel.CurrentStruct.Interface().(User)
258
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")
262         }
263
264         // plus can to more, even with different tag than "fnameorlname"
265 }
266
267 func validateStruct() {
268
269         address := &Address{
270                 Street: "Eavesdown Docks",
271                 Planet: "Persphone",
272                 Phone:  "none",
273                 City:   "Unknown",
274         }
275
276         user := &User{
277                 FirstName:      "",
278                 LastName:       "",
279                 Age:            45,
280                 Email:          "Badger.Smith@gmail.com",
281                 FavouriteColor: "#000",
282                 Addresses:      []*Address{address},
283         }
284
285         // returns nil or ValidationErrors ( map[string]*FieldError )
286         errs := validate.Struct(user)
287
288         if errs != nil {
289
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:
299
300                 // from here you can create your own error messages in whatever language you wish
301                 return
302         }
303
304         // save user to database
305 }
306 ```
307
308 Benchmarks
309 ------
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
311 ```go
312 PASS
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
341 ```
342
343 Complimentary Software
344 ----------------------
345
346 Here is a list of software that compliments using this library either pre or post validation.
347
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.
350
351 How to Contribute
352 ------
353
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.
356
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.
360
361 I strongly encourage everyone whom creates a custom validation function to contribute them and
362 help make this package even better.
363
364 License
365 ------
366 Distributed under MIT License, please see license file in code for more details.