pax_global_header00006660000000000000000000000064126514732260014522gustar00rootroot0000000000000052 comment=9df7e1036fa0767bfedeea8ec25d358e6a95d60e golang-gopkg-validator.v2-0.0+git20160116/000077500000000000000000000000001265147322600176465ustar00rootroot00000000000000golang-gopkg-validator.v2-0.0+git20160116/.gitignore000066400000000000000000000004031265147322600216330ustar00rootroot00000000000000# Compiled Object files, Static and Dynamic libs (Shared Objects) *.o *.a *.so # Folders _obj _test # Architecture specific extensions/prefixes *.[568vq] [568vq].out *.cgo1.go *.cgo2.c _cgo_defun.c _cgo_gotypes.go _cgo_export.* _testmain.go *.exe *.test golang-gopkg-validator.v2-0.0+git20160116/.travis.yml000066400000000000000000000001451265147322600217570ustar00rootroot00000000000000language: go go: - 1.4 - 1.5 script: - go test -race -v -bench=. notifications: email: false golang-gopkg-validator.v2-0.0+git20160116/LICENSE000066400000000000000000000260731265147322600206630ustar00rootroot00000000000000Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.golang-gopkg-validator.v2-0.0+git20160116/README.md000066400000000000000000000117441265147322600211340ustar00rootroot00000000000000Package validator ================ Package validator implements variable validations Installation ============ Just use go get. go get gopkg.in/validator.v2 And then just import the package into your own code. import ( "gopkg.in/validator.v2" ) Usage ===== Please see http://godoc.org/gopkg.in/validator.v2 for detailed usage docs. A simple example would be. type NewUserRequest struct { Username string `validate:"min=3,max=40,regexp=^[a-zA-Z]*$"` Name string `validate:"nonzero"` Age int `validate:"min=21"` Password string `validate:"min=8"` } nur := NewUserRequest{Username: "something", Age: 20} if errs := validator.Validate(nur); errs != nil { // values not valid, deal with errors here } Builtin validators Here is the list of validators buildin in the package. len For numeric numbers, max will simply make sure that the value is equal to the parameter given. For strings, it checks that the string length is exactly that number of characters. For slices, arrays, and maps, validates the number of items. (Usage: len=10) max For numeric numbers, max will simply make sure that the value is lesser or equal to the parameter given. For strings, it checks that the string length is at most that number of characters. For slices, arrays, and maps, validates the number of items. (Usage: max=10) min For numeric numbers, min will simply make sure that the value is greater or equal to the parameter given. For strings, it checks that the string length is at least that number of characters. For slices, arrays, and maps, validates the number of items. (Usage: min=10) nonzero This validates that the value is not zero. The appropriate zero value is given by the Go spec (e.g. for int it's 0, for string it's "", for pointers is nil, etc.) For structs, it will not check to see if the struct itself has all zero values, instead use a pointer or put nonzero on the struct's keys that you care about. (Usage: nonzero) regexp Only valid for string types, it will validator that the value matches the regular expression provided as parameter. (Usage: regexp=^a.*b$) Custom validators It is possible to define custom validators by using SetValidationFunc. First, one needs to create a validation function. // Very simple validator func notZZ(v interface{}, param string) error { st := reflect.ValueOf(v) if st.Kind() != reflect.String { return errors.New("notZZ only validates strings") } if st.String() == "ZZ" { return errors.New("value cannot be ZZ") } return nil } Then one needs to add it to the list of validators and give it a "tag" name. validator.SetValidationFunc("notzz", notZZ) Then it is possible to use the notzz validation tag. This will print "Field A error: value cannot be ZZ" type T struct { A string `validate:"nonzero,notzz"` } t := T{"ZZ"} if errs := validator.Validate(t); errs != nil { fmt.Printf("Field A error: %s\n", errs["A"][0]) } You can also have multiple sets of validator rules with SetTag(). type T struct { A int `foo:"nonzero" bar:"min=10"` } t := T{5} SetTag("foo") validator.Validate(t) // valid as it's nonzero SetTag("bar") validator.Validate(t) // invalid as it's less than 10 SetTag is probably better used with multiple validators. fooValidator := validator.NewValidator() fooValidator.SetTag("foo") barValidator := validator.NewValidator() barValidator.SetTag("bar") fooValidator.Validate(t) barValidator.Validate(t) This keeps the default validator's tag clean. Again, please refer to godocs for a lot of more examples and different uses. Pull requests policy ==================== tl;dr. Contributions are welcome. The repository is organized in version branches. Pull requests to, say, the `v2` branch that break API compatibility will not be accepted. It is okay to break the API in master, *not in the branches*. As for validation functions, the preference is to keep the main code simple and add most new functions to the validator-contrib repository. https://github.com/go-validator/validator-contrib For improvements and/or fixes to the builtin validation functions, please make sure the behaviour will not break existing functionality in the branches. If you see a case where the functionality of the builtin will change significantly, please send a pull request against `master`. We can discuss then whether the changes should be incorporated in the version branches as well. License ======= Copyright 2014 Roberto Teixeira Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. golang-gopkg-validator.v2-0.0+git20160116/builtins.go000066400000000000000000000143521265147322600220330ustar00rootroot00000000000000// Package validator implements value validations // // Copyright 2014 Roberto Teixeira // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package validator import ( "reflect" "regexp" "strconv" ) // nonzero tests whether a variable value non-zero // as defined by the golang spec. func nonzero(v interface{}, param string) error { st := reflect.ValueOf(v) valid := true switch st.Kind() { case reflect.String: valid = len(st.String()) != 0 case reflect.Ptr, reflect.Interface: valid = !st.IsNil() case reflect.Slice, reflect.Map, reflect.Array: valid = st.Len() != 0 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: valid = st.Int() != 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: valid = st.Uint() != 0 case reflect.Float32, reflect.Float64: valid = st.Float() != 0 case reflect.Bool: valid = st.Bool() case reflect.Invalid: valid = false // always invalid case reflect.Struct: valid = true // always valid since only nil pointers are empty default: return ErrUnsupported } if !valid { return ErrZeroValue } return nil } // length tests whether a variable's length is equal to a given // value. For strings it tests the number of characters whereas // for maps and slices it tests the number of items. func length(v interface{}, param string) error { st := reflect.ValueOf(v) valid := true switch st.Kind() { case reflect.String: p, err := asInt(param) if err != nil { return ErrBadParameter } valid = int64(len(st.String())) == p case reflect.Slice, reflect.Map, reflect.Array: p, err := asInt(param) if err != nil { return ErrBadParameter } valid = int64(st.Len()) == p case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: p, err := asInt(param) if err != nil { return ErrBadParameter } valid = st.Int() == p case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: p, err := asUint(param) if err != nil { return ErrBadParameter } valid = st.Uint() == p case reflect.Float32, reflect.Float64: p, err := asFloat(param) if err != nil { return ErrBadParameter } valid = st.Float() == p default: return ErrUnsupported } if !valid { return ErrLen } return nil } // min tests whether a variable value is larger or equal to a given // number. For number types, it's a simple lesser-than test; for // strings it tests the number of characters whereas for maps // and slices it tests the number of items. func min(v interface{}, param string) error { st := reflect.ValueOf(v) invalid := false switch st.Kind() { case reflect.String: p, err := asInt(param) if err != nil { return ErrBadParameter } invalid = int64(len(st.String())) < p case reflect.Slice, reflect.Map, reflect.Array: p, err := asInt(param) if err != nil { return ErrBadParameter } invalid = int64(st.Len()) < p case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: p, err := asInt(param) if err != nil { return ErrBadParameter } invalid = st.Int() < p case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: p, err := asUint(param) if err != nil { return ErrBadParameter } invalid = st.Uint() < p case reflect.Float32, reflect.Float64: p, err := asFloat(param) if err != nil { return ErrBadParameter } invalid = st.Float() < p default: return ErrUnsupported } if invalid { return ErrMin } return nil } // max tests whether a variable value is lesser than a given // value. For numbers, it's a simple lesser-than test; for // strings it tests the number of characters whereas for maps // and slices it tests the number of items. func max(v interface{}, param string) error { st := reflect.ValueOf(v) var invalid bool switch st.Kind() { case reflect.String: p, err := asInt(param) if err != nil { return ErrBadParameter } invalid = int64(len(st.String())) > p case reflect.Slice, reflect.Map, reflect.Array: p, err := asInt(param) if err != nil { return ErrBadParameter } invalid = int64(st.Len()) > p case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: p, err := asInt(param) if err != nil { return ErrBadParameter } invalid = st.Int() > p case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: p, err := asUint(param) if err != nil { return ErrBadParameter } invalid = st.Uint() > p case reflect.Float32, reflect.Float64: p, err := asFloat(param) if err != nil { return ErrBadParameter } invalid = st.Float() > p default: return ErrUnsupported } if invalid { return ErrMax } return nil } // regex is the builtin validation function that checks // whether the string variable matches a regular expression func regex(v interface{}, param string) error { s, ok := v.(string) if !ok { return ErrUnsupported } re, err := regexp.Compile(param) if err != nil { return ErrBadParameter } if !re.MatchString(s) { return ErrRegexp } return nil } // asInt retuns the parameter as a int64 // or panics if it can't convert func asInt(param string) (int64, error) { i, err := strconv.ParseInt(param, 0, 64) if err != nil { return 0, ErrBadParameter } return i, nil } // asUint retuns the parameter as a uint64 // or panics if it can't convert func asUint(param string) (uint64, error) { i, err := strconv.ParseUint(param, 0, 64) if err != nil { return 0, ErrBadParameter } return i, nil } // asFloat retuns the parameter as a float64 // or panics if it can't convert func asFloat(param string) (float64, error) { i, err := strconv.ParseFloat(param, 64) if err != nil { return 0.0, ErrBadParameter } return i, nil } golang-gopkg-validator.v2-0.0+git20160116/doc.go000066400000000000000000000202001265147322600207340ustar00rootroot00000000000000// Package validator implements value validations // // Copyright 2014 Roberto Teixeira // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /* Package validator implements value validations based on struct tags. In code it is often necessary to validate that a given value is valid before using it for something. A typical example might be something like this. if age < 18 { return error.New("age cannot be under 18") } This is a simple enough example, but it can get significantly more complex, especially when dealing with structs. l := len(strings.Trim(s.Username)) if l < 3 || l > 40 || !regexp.MatchString("^[a-zA-Z]$", s.Username) || s.Age < 18 || s.Password { return errors.New("Invalid request") } You get the idea. Package validator allows one to define valid values as struct tags when defining a new struct type. type NewUserRequest struct { Username string `validate:"min=3,max=40,regexp=^[a-zA-Z]$"` Name string `validate:"nonzero"` Age int `validate:"min=18"` Password string `validate:"min=8"` } Then validating a variable of type NewUserRequest becomes trivial. nur := NewUserRequest{Username: "something", ...} if errs := validator.Validate(nur); errs != nil { // do something } Builtin validator functions Here is the list of validator functions builtin in the package. max For numeric numbers, max will simply make sure that the value is equal to the parameter given. For strings, it checks that the string length is exactly that number of characters. For slices, arrays, and maps, validates the number of items. (Usage: len=10) max For numeric numbers, max will simply make sure that the value is lesser or equal to the parameter given. For strings, it checks that the string length is at most that number of characters. For slices, arrays, and maps, validates the number of items. (Usage: max=10) min For numeric numbers, min will simply make sure that the value is greater or equal to the parameter given. For strings, it checks that the string length is at least that number of characters. For slices, arrays, and maps, validates the number of items. (Usage: min=10) nonzero This validates that the value is not zero. The appropriate zero value is given by the Go spec (e.g. for int it's 0, for string it's "", for pointers is nil, etc.) Usage: nonzero regexp Only valid for string types, it will validate that the value matches the regular expression provided as parameter. (Usage: regexp=^a.*b$) Note that there are no tests to prevent conflicting validator parameters. For instance, these fields will never be valid. ... A int `validate:"max=0,min=1"` B string `validate:"len=10,regexp=^$" ... Custom validation functions It is possible to define custom validation functions by using SetValidationFunc. First, one needs to create a validation function. // Very simple validation func func notZZ(v interface{}, param string) error { st := reflect.ValueOf(v) if st.Kind() != reflect.String { return validate.ErrUnsupported } if st.String() == "ZZ" { return errors.New("value cannot be ZZ") } return nil } Then one needs to add it to the list of validation funcs and give it a "tag" name. validate.SetValidationFunc("notzz", notZZ) Then it is possible to use the notzz validation tag. This will print "Field A error: value cannot be ZZ" type T struct { A string `validate:"nonzero,notzz"` } t := T{"ZZ"} if errs := validator.Validate(t); errs != nil { fmt.Printf("Field A error: %s\n", errs["A"][0]) } To use parameters, it is very similar. // Very simple validator with parameter func notSomething(v interface{}, param string) error { st := reflect.ValueOf(v) if st.Kind() != reflect.String { return validate.ErrUnsupported } if st.String() == param { return errors.New("value cannot be " + param) } return nil } And then the code below should print "Field A error: value cannot be ABC". validator.SetValidationFunc("notsomething", notSomething) type T struct { A string `validate:"notsomething=ABC"` } t := T{"ABC"} if errs := validator.Validate(t); errs != nil { fmt.Printf("Field A error: %s\n", errs["A"][0]) } As well, it is possible to overwrite builtin validation functions. validate.SetValidationFunc("min", myMinFunc) And you can delete a validation function by setting it to nil. validate.SetValidationFunc("notzz", nil) validate.SetValidationFunc("nonzero", nil) Using a non-existing validation func in a field tag will always return false and with error validate.ErrUnknownTag. Finally, package validator also provides a helper function that can be used to validate simple variables/values. // errs: nil errs = validator.Valid(42, "min=10, max=50") // errs: [validate.ErrZeroValue] errs = validator.Valid(nil, "nonzero") // errs: [validate.ErrMin,validate.ErrMax] errs = validator.Valid("hi", "nonzero,min=3,max=2") Custom tag name In case there is a reason why one would not wish to use tag 'validate' (maybe due to a conflict with a different package), it is possible to tell the package to use a different tag. validator.SetTag("valid") Then. Type T struct { A int `valid:"min=8, max=10"` B string `valid:"nonzero"` } SetTag is permanent. The new tag name will be used until it is again changed with a new call to SetTag. A way to temporarily use a different tag exists. validator.WithTag("foo").Validate(t) validator.WithTag("bar").Validate(t) // But this will go back to using 'validate' validator.Validate(t) Multiple validators You may often need to have a different set of validation rules for different situations. In all the examples above, we only used the default validator but you could create a new one and set specific rules for it. For instance, you might use the same struct to decode incoming JSON for a REST API but your needs will change when you're using it to, say, create a new instance in storage vs. when you need to change something. type User struct { Username string `validate:"nonzero"` Name string `validate:"nonzero"` Age int `validate:"nonzero"` Password string `validate:"nonzero"` } Maybe when creating a new user, you need to make sure all values in the struct are filled, but then you use the same struct to handle incoming requests to, say, change the password, in which case you only need the Username and the Password and don't care for the others. You might use two different validators. type User struct { Username string `creating:"nonzero" chgpw:"nonzero"` Name string `creating:"nonzero"` Age int `creating:"nonzero"` Password string `creating:"nonzero" chgpw:"nonzero"` } var ( creationValidator = validator.NewValidator() chgPwValidator = validator.NewValidator() ) func init() { creationValidator.SetTag("creating") chgPwValidator.SetTag("chgpw") } ... func CreateUserHandler(w http.ResponseWriter, r *http.Request) { var u User json.NewDecoder(r.Body).Decode(&user) if errs := creationValidator.Validate(user); errs != nil { // the request did not include all of the User // struct fields, so send a http.StatusBadRequest // back or something } // create the new user } func SetNewUserPasswordHandler(w http.ResponseWriter, r *http.Request) { var u User json.NewDecoder(r.Body).Decode(&user) if errs := chgPwValidator.Validate(user); errs != nil { // the request did not Username and Password, // so send a http.StatusBadRequest // back or something } // save the new password } It is also possible to do all of that using only the default validator as long as SetTag is always called before calling validator.Validate() or you chain the with WithTag(). */ package validator golang-gopkg-validator.v2-0.0+git20160116/examplevalidate_test.go000066400000000000000000000102631265147322600244030ustar00rootroot00000000000000// Package validator implements value validations // // Copyright 2014 Roberto Teixeira // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package validator_test import ( "fmt" "sort" "gopkg.in/validator.v2" ) // This example demonstrates a custom function to process template text. // It installs the strings.Title function and uses it to // Make Title Text Look Good In Our Template's Output. func ExampleValidate() { // First create a struct to be validated // according to the validator tags. type ValidateExample struct { Name string `validate:"nonzero"` Description string Age int `validate:"min=18"` Email string `validate:"regexp=^[0-9a-z]+@[0-9a-z]+(\\.[0-9a-z]+)+$"` Address struct { Street string `validate:"nonzero"` City string `validate:"nonzero"` } } // Fill in some values ve := ValidateExample{ Name: "Joe Doe", // valid as it's nonzero Description: "", // valid no validation tag exists Age: 17, // invalid as age is less than required 18 } // invalid as Email won't match the regular expression ve.Email = "@not.a.valid.email" ve.Address.City = "Some City" // valid ve.Address.Street = "" // invalid err := validator.Validate(ve) if err == nil { fmt.Println("Values are valid.") } else { errs := err.(validator.ErrorMap) // See if Address was empty if errs["Address.Street"][0] == validator.ErrZeroValue { fmt.Println("Street cannot be empty.") } // Iterate through the list of fields and respective errors fmt.Println("Invalid due to fields:") // Here we have to sort the arrays to ensure map ordering does not // fail our example, typically it's ok to just range through the err // list when order is not important. var errOuts []string for f, e := range errs { errOuts = append(errOuts, fmt.Sprintf("\t - %s (%v)\n", f, e)) } // Again this part is extraneous and you should not need this in real // code. sort.Strings(errOuts) for _, str := range errOuts { fmt.Print(str) } } // Output: // Street cannot be empty. // Invalid due to fields: // - Address.Street (zero value) // - Age (less than min) // - Email (regular expression mismatch) } // This example shows how to use the Valid helper // function to validator any number of values func ExampleValid() { err := validator.Valid(42, "min=10,max=100,nonzero") fmt.Printf("42: valid=%v, errs=%v\n", err == nil, err) var ptr *int if err := validator.Valid(ptr, "nonzero"); err != nil { fmt.Println("ptr: Invalid nil pointer.") } err = validator.Valid("ABBA", "regexp=[ABC]*") fmt.Printf("ABBA: valid=%v\n", err == nil) // Output: // 42: valid=true, errs= // ptr: Invalid nil pointer. // ABBA: valid=true } // This example shows you how to change the tag name func ExampleSetTag() { type T struct { A int `foo:"nonzero" bar:"min=10"` } t := T{5} v := validator.NewValidator() v.SetTag("foo") err := v.Validate(t) fmt.Printf("foo --> valid: %v, errs: %v\n", err == nil, err) v.SetTag("bar") err = v.Validate(t) errs := err.(validator.ErrorMap) fmt.Printf("bar --> valid: %v, errs: %v\n", err == nil, errs) // Output: // foo --> valid: true, errs: // bar --> valid: false, errs: A: less than min } // This example shows you how to change the tag name func ExampleWithTag() { type T struct { A int `foo:"nonzero" bar:"min=10"` } t := T{5} err := validator.WithTag("foo").Validate(t) fmt.Printf("foo --> valid: %v, errs: %v\n", err == nil, err) err = validator.WithTag("bar").Validate(t) fmt.Printf("bar --> valid: %v, errs: %v\n", err == nil, err) // Output: // foo --> valid: true, errs: // bar --> valid: false, errs: A: less than min } golang-gopkg-validator.v2-0.0+git20160116/validator.go000066400000000000000000000220401265147322600221600ustar00rootroot00000000000000// Package validator implements value validations // // Copyright 2014 Roberto Teixeira // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package validator import ( "errors" "fmt" "reflect" "strings" "unicode" ) // TextErr is an error that also implements the TextMarshaller interface for // serializing out to various plain text encodings. Packages creating their // own custom errors should use TextErr if they're intending to use serializing // formats like json, msgpack etc. type TextErr struct { Err error } // Error implements the error interface. func (t TextErr) Error() string { return t.Err.Error() } // MarshalText implements the TextMarshaller func (t TextErr) MarshalText() ([]byte, error) { return []byte(t.Err.Error()), nil } var ( // ErrZeroValue is the error returned when variable has zero valud // and nonzero was specified ErrZeroValue = TextErr{errors.New("zero value")} // ErrMin is the error returned when variable is less than mininum // value specified ErrMin = TextErr{errors.New("less than min")} // ErrMax is the error returned when variable is more than // maximum specified ErrMax = TextErr{errors.New("greater than max")} // ErrLen is the error returned when length is not equal to // param specified ErrLen = TextErr{errors.New("invalid length")} // ErrRegexp is the error returned when the value does not // match the provided regular expression parameter ErrRegexp = TextErr{errors.New("regular expression mismatch")} // ErrUnsupported is the error error returned when a validation rule // is used with an unsupported variable type ErrUnsupported = TextErr{errors.New("unsupported type")} // ErrBadParameter is the error returned when an invalid parameter // is provided to a validation rule (e.g. a string where an int was // expected (max=foo,len=bar) or missing a parameter when one is required (len=)) ErrBadParameter = TextErr{errors.New("bad parameter")} // ErrUnknownTag is the error returned when an unknown tag is found ErrUnknownTag = TextErr{errors.New("unknown tag")} // ErrInvalid is the error returned when variable is invalid // (normally a nil pointer) ErrInvalid = TextErr{errors.New("invalid value")} ) // ErrorMap is a map which contains all errors from validating a struct. type ErrorMap map[string]ErrorArray // ErrorMap implements the Error interface so we can check error against nil. // The returned error is if existent the first error which was added to the map. func (err ErrorMap) Error() string { for k, errs := range err { if len(errs) > 0 { return fmt.Sprintf("%s: %s", k, errs.Error()) } } return "" } // ErrorArray is a slice of errors returned by the Validate function. type ErrorArray []error // ErrorArray implements the Error interface and returns the first error as // string if existent. func (err ErrorArray) Error() string { if len(err) > 0 { return err[0].Error() } return "" } // ValidationFunc is a function that receives the value of a // field and a parameter used for the respective validation tag. type ValidationFunc func(v interface{}, param string) error // Validator implements a validator type Validator struct { // Tag name being used. tagName string // validationFuncs is a map of ValidationFuncs indexed // by their name. validationFuncs map[string]ValidationFunc } // Helper validator so users can use the // functions directly from the package var defaultValidator = NewValidator() // NewValidator creates a new Validator func NewValidator() *Validator { return &Validator{ tagName: "validate", validationFuncs: map[string]ValidationFunc{ "nonzero": nonzero, "len": length, "min": min, "max": max, "regexp": regex, }, } } // SetTag allows you to change the tag name used in structs func SetTag(tag string) { defaultValidator.SetTag(tag) } // SetTag allows you to change the tag name used in structs func (mv *Validator) SetTag(tag string) { mv.tagName = tag } // WithTag creates a new Validator with the new tag name. It is // useful to chain-call with Validate so we don't change the tag // name permanently: validator.WithTag("foo").Validate(t) func WithTag(tag string) *Validator { return defaultValidator.WithTag(tag) } // WithTag creates a new Validator with the new tag name. It is // useful to chain-call with Validate so we don't change the tag // name permanently: validator.WithTag("foo").Validate(t) func (mv *Validator) WithTag(tag string) *Validator { v := mv.copy() v.SetTag(tag) return v } // Copy a validator func (mv *Validator) copy() *Validator { return &Validator{ tagName: mv.tagName, validationFuncs: mv.validationFuncs, } } // SetValidationFunc sets the function to be used for a given // validation constraint. Calling this function with nil vf // is the same as removing the constraint function from the list. func SetValidationFunc(name string, vf ValidationFunc) error { return defaultValidator.SetValidationFunc(name, vf) } // SetValidationFunc sets the function to be used for a given // validation constraint. Calling this function with nil vf // is the same as removing the constraint function from the list. func (mv *Validator) SetValidationFunc(name string, vf ValidationFunc) error { if name == "" { return errors.New("name cannot be empty") } if vf == nil { delete(mv.validationFuncs, name) return nil } mv.validationFuncs[name] = vf return nil } // Validate validates the fields of a struct based // on 'validator' tags and returns errors found indexed // by the field name. func Validate(v interface{}) error { return defaultValidator.Validate(v) } // Validate validates the fields of a struct based // on 'validator' tags and returns errors found indexed // by the field name. func (mv *Validator) Validate(v interface{}) error { sv := reflect.ValueOf(v) st := reflect.TypeOf(v) if sv.Kind() == reflect.Ptr && !sv.IsNil() { return mv.Validate(sv.Elem().Interface()) } if sv.Kind() != reflect.Struct { return ErrUnsupported } nfields := sv.NumField() m := make(ErrorMap) for i := 0; i < nfields; i++ { f := sv.Field(i) // deal with pointers for f.Kind() == reflect.Ptr && !f.IsNil() { f = f.Elem() } tag := st.Field(i).Tag.Get(mv.tagName) if tag == "-" { continue } fname := st.Field(i).Name var errs ErrorArray if tag != "" { err := mv.Valid(f.Interface(), tag) if errors, ok := err.(ErrorArray); ok { errs = errors } else { if err != nil { errs = ErrorArray{err} } } } if f.Kind() == reflect.Struct { if !unicode.IsUpper(rune(fname[0])) { continue } e := mv.Validate(f.Interface()) if e, ok := e.(ErrorMap); ok && len(e) > 0 { for j, k := range e { m[fname+"."+j] = k } } } if len(errs) > 0 { m[st.Field(i).Name] = errs } } if len(m) > 0 { return m } return nil } // Valid validates a value based on the provided // tags and returns errors found or nil. func Valid(val interface{}, tags string) error { return defaultValidator.Valid(val, tags) } // Valid validates a value based on the provided // tags and returns errors found or nil. func (mv *Validator) Valid(val interface{}, tags string) error { if tags == "-" { return nil } v := reflect.ValueOf(val) if v.Kind() == reflect.Ptr && !v.IsNil() { return mv.Valid(v.Elem().Interface(), tags) } var err error switch v.Kind() { case reflect.Invalid: err = mv.validateVar(nil, tags) default: err = mv.validateVar(val, tags) } return err } // validateVar validates one single variable func (mv *Validator) validateVar(v interface{}, tag string) error { tags, err := mv.parseTags(tag) if err != nil { // unknown tag found, give up. return err } errs := make(ErrorArray, 0, len(tags)) for _, t := range tags { if err := t.Fn(v, t.Param); err != nil { errs = append(errs, err) } } if len(errs) > 0 { return errs } return nil } // tag represents one of the tag items type tag struct { Name string // name of the tag Fn ValidationFunc // validation function to call Param string // parameter to send to the validation function } // parseTags parses all individual tags found within a struct tag. func (mv *Validator) parseTags(t string) ([]tag, error) { tl := strings.Split(t, ",") tags := make([]tag, 0, len(tl)) for _, i := range tl { tg := tag{} v := strings.SplitN(i, "=", 2) tg.Name = strings.Trim(v[0], " ") if tg.Name == "" { return []tag{}, ErrUnknownTag } if len(v) > 1 { tg.Param = strings.Trim(v[1], " ") } var found bool if tg.Fn, found = mv.validationFuncs[tg.Name]; !found { return []tag{}, ErrUnknownTag } tags = append(tags, tg) } return tags, nil } golang-gopkg-validator.v2-0.0+git20160116/validator_test.go000066400000000000000000000225541265147322600232310ustar00rootroot00000000000000// Package validator implements value validations // // Copyright 2014 Roberto Teixeira // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package validator_test import ( "testing" . "gopkg.in/check.v1" "gopkg.in/validator.v2" "reflect" ) func Test(t *testing.T) { TestingT(t) } type MySuite struct{} var _ = Suite(&MySuite{}) type Simple struct { A int `validate:"min=10"` } type TestStruct struct { A int `validate:"nonzero"` B string `validate:"len=8,min=6,max=4"` Sub struct { A int `validate:"nonzero"` B string C float64 `validate:"nonzero,min=1"` D *string `validate:"nonzero"` } D *Simple `validate:"nonzero"` } func (ms *MySuite) TestValidate(c *C) { t := TestStruct{ A: 0, B: "12345", } t.Sub.A = 1 t.Sub.B = "" t.Sub.C = 0.0 t.D = &Simple{10} err := validator.Validate(t) c.Assert(err, NotNil) errs, ok := err.(validator.ErrorMap) c.Assert(ok, Equals, true) c.Assert(errs["A"], HasError, validator.ErrZeroValue) c.Assert(errs["B"], HasError, validator.ErrLen) c.Assert(errs["B"], HasError, validator.ErrMin) c.Assert(errs["B"], HasError, validator.ErrMax) c.Assert(errs["Sub.A"], HasLen, 0) c.Assert(errs["Sub.B"], HasLen, 0) c.Assert(errs["Sub.C"], HasLen, 2) c.Assert(errs["Sub.D"], HasError, validator.ErrZeroValue) } func (ms *MySuite) TestValidSlice(c *C) { s := make([]int, 0, 10) err := validator.Valid(s, "nonzero") c.Assert(err, NotNil) errs, ok := err.(validator.ErrorArray) c.Assert(ok, Equals, true) c.Assert(errs, HasError, validator.ErrZeroValue) for i := 0; i < 10; i++ { s = append(s, i) } err = validator.Valid(s, "min=11,max=5,len=9,nonzero") c.Assert(err, NotNil) errs, ok = err.(validator.ErrorArray) c.Assert(ok, Equals, true) c.Assert(errs, HasError, validator.ErrMin) c.Assert(errs, HasError, validator.ErrMax) c.Assert(errs, HasError, validator.ErrLen) c.Assert(errs, Not(HasError), validator.ErrZeroValue) } func (ms *MySuite) TestValidMap(c *C) { m := make(map[string]string) err := validator.Valid(m, "nonzero") c.Assert(err, NotNil) errs, ok := err.(validator.ErrorArray) c.Assert(ok, Equals, true) c.Assert(errs, HasError, validator.ErrZeroValue) err = validator.Valid(m, "min=1") c.Assert(err, NotNil) errs, ok = err.(validator.ErrorArray) c.Assert(ok, Equals, true) c.Assert(errs, HasError, validator.ErrMin) m = map[string]string{"A": "a", "B": "a"} err = validator.Valid(m, "max=1") c.Assert(err, NotNil) errs, ok = err.(validator.ErrorArray) c.Assert(ok, Equals, true) c.Assert(errs, HasError, validator.ErrMax) err = validator.Valid(m, "min=2, max=5") c.Assert(err, IsNil) m = map[string]string{ "1": "a", "2": "b", "3": "c", "4": "d", "5": "e", } err = validator.Valid(m, "len=4,min=6,max=1,nonzero") c.Assert(err, NotNil) errs, ok = err.(validator.ErrorArray) c.Assert(ok, Equals, true) c.Assert(errs, HasError, validator.ErrLen) c.Assert(errs, HasError, validator.ErrMin) c.Assert(errs, HasError, validator.ErrMax) c.Assert(errs, Not(HasError), validator.ErrZeroValue) } func (ms *MySuite) TestValidFloat(c *C) { err := validator.Valid(12.34, "nonzero") c.Assert(err, IsNil) err = validator.Valid(0.0, "nonzero") c.Assert(err, NotNil) errs, ok := err.(validator.ErrorArray) c.Assert(ok, Equals, true) c.Assert(errs, HasError, validator.ErrZeroValue) } func (ms *MySuite) TestValidInt(c *C) { i := 123 err := validator.Valid(i, "nonzero") c.Assert(err, IsNil) err = validator.Valid(i, "min=1") c.Assert(err, IsNil) err = validator.Valid(i, "min=124, max=122") c.Assert(err, NotNil) errs, ok := err.(validator.ErrorArray) c.Assert(ok, Equals, true) c.Assert(errs, HasError, validator.ErrMin) c.Assert(errs, HasError, validator.ErrMax) err = validator.Valid(i, "max=10") c.Assert(err, NotNil) errs, ok = err.(validator.ErrorArray) c.Assert(ok, Equals, true) c.Assert(errs, HasError, validator.ErrMax) } func (ms *MySuite) TestValidString(c *C) { s := "test1234" err := validator.Valid(s, "len=8") c.Assert(err, IsNil) err = validator.Valid(s, "len=0") c.Assert(err, NotNil) errs, ok := err.(validator.ErrorArray) c.Assert(ok, Equals, true) c.Assert(errs, HasError, validator.ErrLen) err = validator.Valid(s, "regexp=^[tes]{4}.*") c.Assert(err, IsNil) err = validator.Valid(s, "regexp=^.*[0-9]{5}$") c.Assert(errs, NotNil) err = validator.Valid("", "nonzero,len=3,max=1") c.Assert(err, NotNil) errs, ok = err.(validator.ErrorArray) c.Assert(ok, Equals, true) c.Assert(errs, HasLen, 2) c.Assert(errs, HasError, validator.ErrZeroValue) c.Assert(errs, HasError, validator.ErrLen) c.Assert(errs, Not(HasError), validator.ErrMax) } func (ms *MySuite) TestValidateStructVar(c *C) { // just verifies that a the given val is a struct validator.SetValidationFunc("struct", func(val interface{}, _ string) error { v := reflect.ValueOf(val) if v.Kind() == reflect.Struct { return nil } return validator.ErrUnsupported }) type test struct { A int } err := validator.Valid(test{}, "struct") c.Assert(err, IsNil) type test2 struct { B int } type test1 struct { A test2 `validate:"struct"` } err = validator.Validate(test1{}) c.Assert(err, IsNil) type test4 struct { B int `validate:"foo"` } type test3 struct { A test4 } err = validator.Validate(test3{}) errs, ok := err.(validator.ErrorMap) c.Assert(ok, Equals, true) c.Assert(errs["A.B"], HasError, validator.ErrUnknownTag) } func (ms *MySuite) TestValidatePointerVar(c *C) { // just verifies that a the given val is a struct validator.SetValidationFunc("struct", func(val interface{}, _ string) error { v := reflect.ValueOf(val) if v.Kind() == reflect.Struct { return nil } return validator.ErrUnsupported }) validator.SetValidationFunc("nil", func(val interface{}, _ string) error { v := reflect.ValueOf(val) if v.IsNil() { return nil } return validator.ErrUnsupported }) type test struct { A int } err := validator.Valid(&test{}, "struct") c.Assert(err, IsNil) type test2 struct { B int } type test1 struct { A *test2 `validate:"struct"` } err = validator.Validate(&test1{&test2{}}) c.Assert(err, IsNil) type test4 struct { B int `validate:"foo"` } type test3 struct { A test4 } err = validator.Validate(&test3{}) errs, ok := err.(validator.ErrorMap) c.Assert(ok, Equals, true) c.Assert(errs["A.B"], HasError, validator.ErrUnknownTag) err = validator.Valid((*test)(nil), "nil") c.Assert(err, IsNil) type test5 struct { A *test2 `validate:"nil"` } err = validator.Validate(&test5{}) c.Assert(err, IsNil) type test6 struct { A *test2 `validate:"nonzero"` } err = validator.Validate(&test6{}) errs, ok = err.(validator.ErrorMap) c.Assert(ok, Equals, true) c.Assert(errs["A"], HasError, validator.ErrZeroValue) err = validator.Validate(&test6{&test2{}}) c.Assert(err, IsNil) } func (ms *MySuite) TestValidateOmittedStructVar(c *C) { type test2 struct { B int `validate:"min=1"` } type test1 struct { A test2 `validate:"-"` } t := test1{} err := validator.Validate(t) c.Assert(err, IsNil) errs := validator.Valid(test2{}, "-") c.Assert(errs, IsNil) } func (ms *MySuite) TestUnknownTag(c *C) { type test struct { A int `validate:"foo"` } t := test{} err := validator.Validate(t) c.Assert(err, NotNil) errs, ok := err.(validator.ErrorMap) c.Assert(ok, Equals, true) c.Assert(errs, HasLen, 1) c.Assert(errs["A"], HasError, validator.ErrUnknownTag) } func (ms *MySuite) TestUnsupported(c *C) { type test struct { A int `validate:"regexp=a.*b"` B float64 `validate:"regexp=.*"` } t := test{} err := validator.Validate(t) c.Assert(err, NotNil) errs, ok := err.(validator.ErrorMap) c.Assert(ok, Equals, true) c.Assert(errs, HasLen, 2) c.Assert(errs["A"], HasError, validator.ErrUnsupported) c.Assert(errs["B"], HasError, validator.ErrUnsupported) } func (ms *MySuite) TestBadParameter(c *C) { type test struct { A string `validate:"min="` B string `validate:"len=="` C string `validate:"max=foo"` } t := test{} err := validator.Validate(t) c.Assert(err, NotNil) errs, ok := err.(validator.ErrorMap) c.Assert(ok, Equals, true) c.Assert(errs, HasLen, 3) c.Assert(errs["A"], HasError, validator.ErrBadParameter) c.Assert(errs["B"], HasError, validator.ErrBadParameter) c.Assert(errs["C"], HasError, validator.ErrBadParameter) } type hasErrorChecker struct { *CheckerInfo } func (c *hasErrorChecker) Check(params []interface{}, names []string) (bool, string) { var ( ok bool slice []error value error ) slice, ok = params[0].(validator.ErrorArray) if !ok { return false, "First parameter is not an Errorarray" } value, ok = params[1].(error) if !ok { return false, "Second parameter is not an error" } for _, v := range slice { if v == value { return true, "" } } return false, "" } func (c *hasErrorChecker) Info() *CheckerInfo { return c.CheckerInfo } var HasError = &hasErrorChecker{&CheckerInfo{Name: "HasError", Params: []string{"HasError", "expected to contain"}}}