Codebase list golang-github-go-playground-validator-v10 / cca78d79-2c5a-433f-ac92-5bbed0c9b1bb/upstream
Import upstream version 10.6.1 Debian Janitor 2 years ago
25 changed file(s) with 1037 addition(s) and 385 deletion(s). Raw diff Collapse all Expand all
0 * @go-playground/validator-maintainers
11
22 ## Quality Standard
33
4 To ensure the continued stability of this package, tests are required to be written or already exist in order for a pull request to be merged.
4 To ensure the continued stability of this package, tests are required that cover the change in order for a pull request to be merged.
55
66 ## Reporting issues
77
0 ### Package version eg. v8, v9:
0 - [ ] I have looked at the documentation [here](https://pkg.go.dev/github.com/go-playground/validator/v10#section-documentation) first?
1 - [ ] I have looked at the examples provided that may showcase my question [here](/_examples)?
2
3 ### Package version eg. v9, v10:
14
25
36
0 Fixes Or Enhances # .
0 ## Fixes Or Enhances
1
12
23 **Make sure that you've checked the boxes below before you submit PR:**
34 - [ ] Tests exist or have been written that cover this particular change.
45
5 Change Details:
6
7 -
8 -
9 -
10
11
12 @go-playground/admins
6 @go-playground/validator-maintainers
0 on:
1 push:
2 branches:
3 - master
4 pull_request:
5 name: Test
6 jobs:
7 test:
8 strategy:
9 matrix:
10 go-version: [1.15.x, 1.16.x]
11 os: [ubuntu-latest, macos-latest, windows-latest]
12 runs-on: ${{ matrix.os }}
13 steps:
14 - name: Install Go
15 uses: actions/setup-go@v2
16 with:
17 go-version: ${{ matrix.go-version }}
18
19 - name: Checkout code
20 uses: actions/checkout@v2
21
22 - name: Restore Cache
23 uses: actions/cache@v2
24 with:
25 path: ~/go/pkg/mod
26 key: ${{ runner.os }}-v1-go-${{ hashFiles('**/go.sum') }}
27 restore-keys: |
28 ${{ runner.os }}-v1-go-
29
30 - name: Test
31 run: go test -race -covermode=atomic -coverprofile="profile.cov" ./...
32
33 - name: Send Coverage
34 if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.16.x'
35 uses: shogo82148/actions-goveralls@v1
36 with:
37 path-to-profile: profile.cov
38
39 golangci:
40 name: lint
41 runs-on: ubuntu-latest
42 steps:
43 - uses: actions/checkout@v2
44 - name: golangci-lint
45 uses: golangci/golangci-lint-action@v2
46 with:
47 version: v1.39
+0
-29
.travis.yml less more
0 language: go
1 go:
2 - 1.15.2
3 - tip
4 matrix:
5 allow_failures:
6 - go: tip
7
8 notifications:
9 email:
10 recipients: dean.karn@gmail.com
11 on_success: change
12 on_failure: always
13
14 before_install:
15 - go install github.com/mattn/goveralls
16 - mkdir -p $GOPATH/src/gopkg.in
17 - ln -s $GOPATH/src/github.com/$TRAVIS_REPO_SLUG $GOPATH/src/gopkg.in/validator.v9
18
19 # Only clone the most recent commit.
20 git:
21 depth: 1
22
23 script:
24 - go test -v -race -covermode=atomic -coverprofile=coverage.coverprofile ./...
25
26 after_success: |
27 [ $TRAVIS_GO_VERSION = 1.15.2 ] &&
28 goveralls -coverprofile=coverage.coverprofile -service travis-ci -repotoken $COVERALLS_TOKEN
0 ## Maintainers Guide
1
2 ### Semantic Versioning
3 Semantic versioning as defined [here](https://semver.org) must be strictly adhered to.
4
5 ### External Dependencies
6 Any new external dependencies MUST:
7 - Have a compatible LICENSE present.
8 - Be actively maintained.
9 - Be approved by @go-playground/admins
10
11 ### PR Merge Requirements
12 - Up-to-date branch.
13 - Passing tests and linting.
14 - CODEOWNERS approval.
15 - Tests that cover both the Happy and Unhappy paths.
22 linters-install:
33 @golangci-lint --version >/dev/null 2>&1 || { \
44 echo "installing linting tools..."; \
5 curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s v1.21.0; \
5 curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s v1.39.0; \
66 }
77
88 lint: linters-install
9 $(PWD)/bin/golangci-lint run
9 golangci-lint run
1010
1111 test:
1212 $(GOCMD) test -cover -race ./...
00 Package validator
1 ================
1 =================
22 <img align="right" src="https://raw.githubusercontent.com/go-playground/validator/v9/logo.png">[![Join the chat at https://gitter.im/go-playground/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)
3 ![Project status](https://img.shields.io/badge/version-10.4.1-green.svg)
3 ![Project status](https://img.shields.io/badge/version-10.6.1-green.svg)
44 [![Build Status](https://travis-ci.org/go-playground/validator.svg?branch=master)](https://travis-ci.org/go-playground/validator)
55 [![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=master&service=github)](https://coveralls.io/github/go-playground/validator?branch=master)
66 [![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator)
2626
2727 Use go get.
2828
29 go get github.com/go-playground/validator/v10
29 go get github.com/go-playground/validator
3030
3131 Then import the validator package into your own code.
3232
33 import "github.com/go-playground/validator/v10"
33 import "github.com/go-playground/validator"
3434
3535 Error Return Value
3636 -------
5252 Usage and documentation
5353 ------
5454
55 Please see https://godoc.org/github.com/go-playground/validator for detailed usage docs.
55 Please see https://pkg.go.dev/github.com/go-playground/validator/v10 for detailed usage docs.
5656
5757 ##### Examples:
5858
294294 Make a pull request...
295295
296296 License
297 ------
297 -------
298298 Distributed under MIT License, please see license file within the code for more details.
299
300 Maintainers
301 -----------
302 This project has grown large enough that more than one person is required to properly support the community.
303 If you are interested in becoming a maintainer please reach out to me https://github.com/deankarn
0 package main
1
2 import (
3 "fmt"
4 "github.com/go-playground/validator/v10"
5 )
6
7 var validate *validator.Validate
8
9 func main() {
10 validate = validator.New()
11
12 validateMap()
13 validateNestedMap()
14 }
15
16 func validateMap() {
17 user := map[string]interface{}{"name": "Arshiya Kiani", "email": "zytel3301@gmail.com"}
18
19 // Every rule will be applied to the item of the data that the offset of rule is pointing to.
20 // So if you have a field "email": "omitempty,required,email", the validator will apply these
21 // rules to offset of email in user data
22 rules := map[string]interface{}{"name": "required,min=8,max=32", "email": "omitempty,required,email"}
23
24 // ValidateMap will return map[string]error.
25 // The offset of every item in errs is the name of invalid field and the value
26 // is the message of error. If there was no error, ValidateMap method will
27 // return an EMPTY map of errors, not nil. If you want to check that
28 // if there was an error or not, you must check the length of the return value
29 errs := validate.ValidateMap(user, rules)
30
31 if len(errs) > 0 {
32 fmt.Println(errs)
33 // The user is invalid
34 }
35
36 // The user is valid
37 }
38
39 func validateNestedMap() {
40
41 data := map[string]interface{}{
42 "name": "Arshiya Kiani",
43 "email": "zytel3301@gmail.com",
44 "details": map[string]interface{}{
45 "family_members": map[string]interface{}{
46 "father_name": "Micheal",
47 "mother_name": "Hannah",
48 },
49 "salary": "1000",
50 },
51 }
52
53 // Rules must be set as the structure as the data itself. If you want to dive into the
54 // map, just declare its rules as a map
55 rules := map[string]interface{}{
56 "name": "min=4,max=32",
57 "email": "required,email",
58 "details": map[string]interface{}{
59 "family_members": map[string]interface{}{
60 "father_name": "required,min=4,max=32",
61 "mother_name": "required,min=4,max=32",
62 },
63 "salary": "number",
64 },
65 }
66
67 if len(validate.ValidateMap(data, rules)) == 0 {
68 // Data is valid
69 }
70
71 // Data is invalid
72 }
4343
4444 // register validation for 'User'
4545 // NOTE: only have to register a non-pointer type for 'User', validator
46 // interanlly dereferences during it's type checks.
46 // internally dereferences during it's type checks.
4747 validate.RegisterStructValidation(UserStructLevelValidation, User{})
4848
4949 // build 'User' info, normally posted data etc...
1717 "unicode/utf8"
1818
1919 "golang.org/x/crypto/sha3"
20 "golang.org/x/text/language"
2021
2122 urn "github.com/leodido/go-urn"
2223 )
6667 // you can add, remove or even replace items to suite your needs,
6768 // or even disregard and use your own map if so desired.
6869 bakedInValidators = map[string]Func{
69 "required": hasValue,
70 "required_if": requiredIf,
71 "required_unless": requiredUnless,
72 "required_with": requiredWith,
73 "required_with_all": requiredWithAll,
74 "required_without": requiredWithout,
75 "required_without_all": requiredWithoutAll,
76 "excluded_with": excludedWith,
77 "excluded_with_all": excludedWithAll,
78 "excluded_without": excludedWithout,
79 "excluded_without_all": excludedWithoutAll,
80 "isdefault": isDefault,
81 "len": hasLengthOf,
82 "min": hasMinOf,
83 "max": hasMaxOf,
84 "eq": isEq,
85 "ne": isNe,
86 "lt": isLt,
87 "lte": isLte,
88 "gt": isGt,
89 "gte": isGte,
90 "eqfield": isEqField,
91 "eqcsfield": isEqCrossStructField,
92 "necsfield": isNeCrossStructField,
93 "gtcsfield": isGtCrossStructField,
94 "gtecsfield": isGteCrossStructField,
95 "ltcsfield": isLtCrossStructField,
96 "ltecsfield": isLteCrossStructField,
97 "nefield": isNeField,
98 "gtefield": isGteField,
99 "gtfield": isGtField,
100 "ltefield": isLteField,
101 "ltfield": isLtField,
102 "fieldcontains": fieldContains,
103 "fieldexcludes": fieldExcludes,
104 "alpha": isAlpha,
105 "alphanum": isAlphanum,
106 "alphaunicode": isAlphaUnicode,
107 "alphanumunicode": isAlphanumUnicode,
108 "numeric": isNumeric,
109 "number": isNumber,
110 "hexadecimal": isHexadecimal,
111 "hexcolor": isHEXColor,
112 "rgb": isRGB,
113 "rgba": isRGBA,
114 "hsl": isHSL,
115 "hsla": isHSLA,
116 "e164": isE164,
117 "email": isEmail,
118 "url": isURL,
119 "uri": isURI,
120 "urn_rfc2141": isUrnRFC2141, // RFC 2141
121 "file": isFile,
122 "base64": isBase64,
123 "base64url": isBase64URL,
124 "contains": contains,
125 "containsany": containsAny,
126 "containsrune": containsRune,
127 "excludes": excludes,
128 "excludesall": excludesAll,
129 "excludesrune": excludesRune,
130 "startswith": startsWith,
131 "endswith": endsWith,
132 "startsnotwith": startsNotWith,
133 "endsnotwith": endsNotWith,
134 "isbn": isISBN,
135 "isbn10": isISBN10,
136 "isbn13": isISBN13,
137 "eth_addr": isEthereumAddress,
138 "btc_addr": isBitcoinAddress,
139 "btc_addr_bech32": isBitcoinBech32Address,
140 "uuid": isUUID,
141 "uuid3": isUUID3,
142 "uuid4": isUUID4,
143 "uuid5": isUUID5,
144 "uuid_rfc4122": isUUIDRFC4122,
145 "uuid3_rfc4122": isUUID3RFC4122,
146 "uuid4_rfc4122": isUUID4RFC4122,
147 "uuid5_rfc4122": isUUID5RFC4122,
148 "ascii": isASCII,
149 "printascii": isPrintableASCII,
150 "multibyte": hasMultiByteCharacter,
151 "datauri": isDataURI,
152 "latitude": isLatitude,
153 "longitude": isLongitude,
154 "ssn": isSSN,
155 "ipv4": isIPv4,
156 "ipv6": isIPv6,
157 "ip": isIP,
158 "cidrv4": isCIDRv4,
159 "cidrv6": isCIDRv6,
160 "cidr": isCIDR,
161 "tcp4_addr": isTCP4AddrResolvable,
162 "tcp6_addr": isTCP6AddrResolvable,
163 "tcp_addr": isTCPAddrResolvable,
164 "udp4_addr": isUDP4AddrResolvable,
165 "udp6_addr": isUDP6AddrResolvable,
166 "udp_addr": isUDPAddrResolvable,
167 "ip4_addr": isIP4AddrResolvable,
168 "ip6_addr": isIP6AddrResolvable,
169 "ip_addr": isIPAddrResolvable,
170 "unix_addr": isUnixAddrResolvable,
171 "mac": isMAC,
172 "hostname": isHostnameRFC952, // RFC 952
173 "hostname_rfc1123": isHostnameRFC1123, // RFC 1123
174 "fqdn": isFQDN,
175 "unique": isUnique,
176 "oneof": isOneOf,
177 "html": isHTML,
178 "html_encoded": isHTMLEncoded,
179 "url_encoded": isURLEncoded,
180 "dir": isDir,
181 "json": isJSON,
182 "hostname_port": isHostnamePort,
183 "lowercase": isLowercase,
184 "uppercase": isUppercase,
185 "datetime": isDatetime,
186 "timezone": isTimeZone,
187 "iso3166_1_alpha2": isIso3166Alpha2,
188 "iso3166_1_alpha3": isIso3166Alpha3,
189 "iso3166_1_alpha_numeric": isIso3166AlphaNumeric,
70 "required": hasValue,
71 "required_if": requiredIf,
72 "required_unless": requiredUnless,
73 "required_with": requiredWith,
74 "required_with_all": requiredWithAll,
75 "required_without": requiredWithout,
76 "required_without_all": requiredWithoutAll,
77 "excluded_with": excludedWith,
78 "excluded_with_all": excludedWithAll,
79 "excluded_without": excludedWithout,
80 "excluded_without_all": excludedWithoutAll,
81 "isdefault": isDefault,
82 "len": hasLengthOf,
83 "min": hasMinOf,
84 "max": hasMaxOf,
85 "eq": isEq,
86 "ne": isNe,
87 "lt": isLt,
88 "lte": isLte,
89 "gt": isGt,
90 "gte": isGte,
91 "eqfield": isEqField,
92 "eqcsfield": isEqCrossStructField,
93 "necsfield": isNeCrossStructField,
94 "gtcsfield": isGtCrossStructField,
95 "gtecsfield": isGteCrossStructField,
96 "ltcsfield": isLtCrossStructField,
97 "ltecsfield": isLteCrossStructField,
98 "nefield": isNeField,
99 "gtefield": isGteField,
100 "gtfield": isGtField,
101 "ltefield": isLteField,
102 "ltfield": isLtField,
103 "fieldcontains": fieldContains,
104 "fieldexcludes": fieldExcludes,
105 "alpha": isAlpha,
106 "alphanum": isAlphanum,
107 "alphaunicode": isAlphaUnicode,
108 "alphanumunicode": isAlphanumUnicode,
109 "numeric": isNumeric,
110 "number": isNumber,
111 "hexadecimal": isHexadecimal,
112 "hexcolor": isHEXColor,
113 "rgb": isRGB,
114 "rgba": isRGBA,
115 "hsl": isHSL,
116 "hsla": isHSLA,
117 "e164": isE164,
118 "email": isEmail,
119 "url": isURL,
120 "uri": isURI,
121 "urn_rfc2141": isUrnRFC2141, // RFC 2141
122 "file": isFile,
123 "base64": isBase64,
124 "base64url": isBase64URL,
125 "contains": contains,
126 "containsany": containsAny,
127 "containsrune": containsRune,
128 "excludes": excludes,
129 "excludesall": excludesAll,
130 "excludesrune": excludesRune,
131 "startswith": startsWith,
132 "endswith": endsWith,
133 "startsnotwith": startsNotWith,
134 "endsnotwith": endsNotWith,
135 "isbn": isISBN,
136 "isbn10": isISBN10,
137 "isbn13": isISBN13,
138 "eth_addr": isEthereumAddress,
139 "btc_addr": isBitcoinAddress,
140 "btc_addr_bech32": isBitcoinBech32Address,
141 "uuid": isUUID,
142 "uuid3": isUUID3,
143 "uuid4": isUUID4,
144 "uuid5": isUUID5,
145 "uuid_rfc4122": isUUIDRFC4122,
146 "uuid3_rfc4122": isUUID3RFC4122,
147 "uuid4_rfc4122": isUUID4RFC4122,
148 "uuid5_rfc4122": isUUID5RFC4122,
149 "ascii": isASCII,
150 "printascii": isPrintableASCII,
151 "multibyte": hasMultiByteCharacter,
152 "datauri": isDataURI,
153 "latitude": isLatitude,
154 "longitude": isLongitude,
155 "ssn": isSSN,
156 "ipv4": isIPv4,
157 "ipv6": isIPv6,
158 "ip": isIP,
159 "cidrv4": isCIDRv4,
160 "cidrv6": isCIDRv6,
161 "cidr": isCIDR,
162 "tcp4_addr": isTCP4AddrResolvable,
163 "tcp6_addr": isTCP6AddrResolvable,
164 "tcp_addr": isTCPAddrResolvable,
165 "udp4_addr": isUDP4AddrResolvable,
166 "udp6_addr": isUDP6AddrResolvable,
167 "udp_addr": isUDPAddrResolvable,
168 "ip4_addr": isIP4AddrResolvable,
169 "ip6_addr": isIP6AddrResolvable,
170 "ip_addr": isIPAddrResolvable,
171 "unix_addr": isUnixAddrResolvable,
172 "mac": isMAC,
173 "hostname": isHostnameRFC952, // RFC 952
174 "hostname_rfc1123": isHostnameRFC1123, // RFC 1123
175 "fqdn": isFQDN,
176 "unique": isUnique,
177 "oneof": isOneOf,
178 "html": isHTML,
179 "html_encoded": isHTMLEncoded,
180 "url_encoded": isURLEncoded,
181 "dir": isDir,
182 "json": isJSON,
183 "hostname_port": isHostnamePort,
184 "lowercase": isLowercase,
185 "uppercase": isUppercase,
186 "datetime": isDatetime,
187 "timezone": isTimeZone,
188 "iso3166_1_alpha2": isIso3166Alpha2,
189 "iso3166_1_alpha3": isIso3166Alpha3,
190 "iso3166_1_alpha_numeric": isIso3166AlphaNumeric,
191 "bcp47_language_tag": isBCP47LanguageTag,
192 "postcode_iso3166_alpha2": isPostcodeByIso3166Alpha2,
193 "postcode_iso3166_alpha2_field": isPostcodeByIso3166Alpha2Field,
194 "bic": isIsoBicFormat,
190195 }
191196 )
192197
546551 return false
547552 }
548553
549 if ethaddressRegexUpper.MatchString(address) || ethAddressRegexLower.MatchString(address) {
554 if ethAddressRegexUpper.MatchString(address) || ethAddressRegexLower.MatchString(address) {
550555 return true
551556 }
552557
790795 case reflect.Slice, reflect.Map, reflect.Array:
791796 return int64(field.Len()) != int64(currentField.Len())
792797
798 case reflect.Bool:
799 return field.Bool() != currentField.Bool()
800
793801 case reflect.Struct:
794802
795803 fieldType := field.Type()
10321040 case reflect.Slice, reflect.Map, reflect.Array:
10331041 return int64(topField.Len()) != int64(field.Len())
10341042
1043 case reflect.Bool:
1044 return topField.Bool() != field.Bool()
1045
10351046 case reflect.Struct:
10361047
10371048 fieldType := field.Type()
10791090 case reflect.Slice, reflect.Map, reflect.Array:
10801091 return int64(topField.Len()) == int64(field.Len())
10811092
1093 case reflect.Bool:
1094 return topField.Bool() == field.Bool()
1095
10821096 case reflect.Struct:
10831097
10841098 fieldType := field.Type()
11261140 case reflect.Slice, reflect.Map, reflect.Array:
11271141 return int64(field.Len()) == int64(currentField.Len())
11281142
1143 case reflect.Bool:
1144 return field.Bool() == currentField.Bool()
1145
11291146 case reflect.Struct:
11301147
11311148 fieldType := field.Type()
11871204 }
11881205
11891206 panic(fmt.Sprintf("Bad field type %T", field.Interface()))
1207 }
1208
1209 // isPostcodeByIso3166Alpha2 validates by value which is country code in iso 3166 alpha 2
1210 // example: `postcode_iso3166_alpha2=US`
1211 func isPostcodeByIso3166Alpha2(fl FieldLevel) bool {
1212 field := fl.Field()
1213 param := fl.Param()
1214
1215 reg, found := postCodeRegexDict[param]
1216 if !found {
1217 return false
1218 }
1219
1220 return reg.MatchString(field.String())
1221 }
1222
1223 // isPostcodeByIso3166Alpha2 validates by field which represents for a value of country code in iso 3166 alpha 2
1224 // example: `postcode_iso3166_alpha2_field=CountryCode`
1225 func isPostcodeByIso3166Alpha2Field(fl FieldLevel) bool {
1226 field := fl.Field()
1227 params := parseOneOfParam2(fl.Param())
1228
1229 if len(params) != 1 {
1230 return false
1231 }
1232
1233 currentField, kind, _, found := fl.GetStructFieldOKAdvanced2(fl.Parent(), params[0])
1234 if !found {
1235 return false
1236 }
1237
1238 if kind != reflect.String {
1239 panic(fmt.Sprintf("Bad field type %T", currentField.Interface()))
1240 }
1241
1242 reg, found := postCodeRegexDict[currentField.String()]
1243 if !found {
1244 return false
1245 }
1246
1247 return reg.MatchString(field.String())
11901248 }
11911249
11921250 // IsBase64 is the validation function for validating if the current field's value is a valid base 64.
13291387
13301388 // IsHEXColor is the validation function for validating if the current field's value is a valid HEX color.
13311389 func isHEXColor(fl FieldLevel) bool {
1332 return hexcolorRegex.MatchString(fl.Field().String())
1390 return hexColorRegex.MatchString(fl.Field().String())
13331391 }
13341392
13351393 // IsHexadecimal is the validation function for validating if the current field's value is a valid hexadecimal.
14401498
14411499 case reflect.Slice, reflect.Map, reflect.Array:
14421500 return int64(field.Len()) == asInt(value)
1501
1502 case reflect.Bool:
1503 return field.Bool() == asBool(value)
14431504 }
14441505
14451506 // default reflect.String:
15431604 return true
15441605 }
15451606
1546 // RequiredWithoutAll is the validation function
1607 // ExcludedWithoutAll is the validation function
15471608 // The field under validation must not be present or is empty when all of the other specified fields are not present.
15481609 func excludedWithoutAll(fl FieldLevel) bool {
15491610 params := parseOneOfParam2(fl.Param())
22822343 }
22832344 return iso3166_1_alpha_numeric[code]
22842345 }
2346
2347 // isBCP47LanguageTag is the validation function for validating if the current field's value is a valid BCP 47 language tag, as parsed by language.Parse
2348 func isBCP47LanguageTag(fl FieldLevel) bool {
2349 field := fl.Field()
2350
2351 if field.Kind() == reflect.String {
2352 _, err := language.Parse(field.String())
2353 return err == nil
2354 }
2355
2356 panic(fmt.Sprintf("Bad field type %T", field.Interface()))
2357 }
2358
2359 // isIsoBicFormat is the validation function for validating if the current field's value is a valid Business Identifier Code (SWIFT code), defined in ISO 9362
2360 func isIsoBicFormat(fl FieldLevel) bool {
2361 bicString := fl.Field().String()
2362
2363 return bicRegex.MatchString(bicString)
2364 }
12201220
12211221 Usage: iso3166_1_alpha3
12221222
1223 BCP 47 Language Tag
1224
1225 This validates that a string value is a valid BCP 47 language tag, as parsed by language.Parse.
1226 More information on https://pkg.go.dev/golang.org/x/text/language
1227
1228 Usage: bcp47_language_tag
1229
1230 BIC (SWIFT code)
1231
1232 This validates that a string value is a valid Business Identifier Code (SWIFT code), defined in ISO 9362.
1233 More information on https://www.iso.org/standard/60390.html
1234
1235 Usage: bic
1236
12231237 TimeZone
12241238
12251239 This validates that a string value is a valid time zone based on the time zone database present on the system.
12271241 More information on https://golang.org/pkg/time/#LoadLocation
12281242
12291243 Usage: timezone
1230
1244
12311245
12321246 Alias Validators and Tags
12331247
8181 // FieldError contains all functions to get error details
8282 type FieldError interface {
8383
84 // returns the validation tag that failed. if the
84 // Tag returns the validation tag that failed. if the
8585 // validation was an alias, this will return the
8686 // alias name and not the underlying tag that failed.
8787 //
8989 // will return "iscolor"
9090 Tag() string
9191
92 // returns the validation tag that failed, even if an
92 // ActualTag returns the validation tag that failed, even if an
9393 // alias the actual tag within the alias will be returned.
9494 // If an 'or' validation fails the entire or will be returned.
9595 //
9797 // will return "hexcolor|rgb|rgba|hsl|hsla"
9898 ActualTag() string
9999
100 // returns the namespace for the field error, with the tag
100 // Namespace returns the namespace for the field error, with the tag
101101 // name taking precedence over the field's actual name.
102102 //
103103 // eg. JSON name "User.fname"
108108 // using validate.Field(...) as there is no way to extract it's name
109109 Namespace() string
110110
111 // returns the namespace for the field error, with the field's
111 // StructNamespace returns the namespace for the field error, with the field's
112112 // actual name.
113113 //
114114 // eq. "User.FirstName" see Namespace for comparison
117117 // using validate.Field(...) as there is no way to extract its name
118118 StructNamespace() string
119119
120 // returns the fields name with the tag name taking precedence over the
120 // Field returns the fields name with the tag name taking precedence over the
121121 // field's actual name.
122122 //
123123 // eq. JSON name "fname"
124124 // see StructField for comparison
125125 Field() string
126126
127 // returns the field's actual name from the struct, when able to determine.
127 // StructField returns the field's actual name from the struct, when able to determine.
128128 //
129129 // eq. "FirstName"
130130 // see Field for comparison
131131 StructField() string
132132
133 // returns the actual field's value in case needed for creating the error
133 // Value returns the actual field's value in case needed for creating the error
134134 // message
135135 Value() interface{}
136136
137 // returns the param value, in string form for comparison; this will also
137 // Param returns the param value, in string form for comparison; this will also
138138 // help with generating an error message
139139 Param() string
140140
145145
146146 // Type returns the Field's reflect Type
147147 //
148 // // eg. time.Time's type is time.Time
148 // eg. time.Time's type is time.Time
149149 Type() reflect.Type
150150
151 // returns the FieldError's translated error
151 // Translate returns the FieldError's translated error
152152 // from the provided 'ut.Translator' and registered 'TranslationFunc'
153153 //
154154 // NOTE: if no registered translator can be found it returns the same as
220220 // return fld
221221 }
222222
223 // returns the field's actual name from the struct, when able to determine.
223 // StructField returns the field's actual name from the struct, when able to determine.
224224 func (fe *fieldError) StructField() string {
225225 // return fe.structField
226226 return fe.structNs[len(fe.structNs)-int(fe.structfieldLen):]
44 // FieldLevel contains all the information and helper functions
55 // to validate a field
66 type FieldLevel interface {
7 // returns the top level struct, if any
7
8 // Top returns the top level struct, if any
89 Top() reflect.Value
910
10 // returns the current fields parent struct, if any or
11 // Parent returns the current fields parent struct, if any or
1112 // the comparison value if called 'VarWithValue'
1213 Parent() reflect.Value
1314
14 // returns current field for validation
15 // Field returns current field for validation
1516 Field() reflect.Value
1617
17 // returns the field's name with the tag
18 // FieldName returns the field's name with the tag
1819 // name taking precedence over the fields actual name.
1920 FieldName() string
2021
21 // returns the struct field's name
22 // StructFieldName returns the struct field's name
2223 StructFieldName() string
2324
24 // returns param for validation against current field
25 // Param returns param for validation against current field
2526 Param() string
2627
2728 // GetTag returns the current validations tag name
3233 // underlying value and it's kind.
3334 ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool)
3435
35 // traverses the parent struct to retrieve a specific field denoted by the provided namespace
36 // GetStructFieldOK traverses the parent struct to retrieve a specific field denoted by the provided namespace
3637 // in the param and returns the field, field kind and whether is was successful in retrieving
3738 // the field at all.
3839 //
4849 // Deprecated: Use GetStructFieldOKAdvanced2() instead which also return if the value is nullable.
4950 GetStructFieldOKAdvanced(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool)
5051
51 // traverses the parent struct to retrieve a specific field denoted by the provided namespace
52 // GetStructFieldOK2 traverses the parent struct to retrieve a specific field denoted by the provided namespace
5253 // in the param and returns the field, field kind, if it's a nullable type and whether is was successful in retrieving
5354 // the field at all.
5455 //
5657 // could not be retrieved because it didn't exist.
5758 GetStructFieldOK2() (reflect.Value, reflect.Kind, bool, bool)
5859
59 // GetStructFieldOKAdvanced is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
60 // GetStructFieldOKAdvanced2 is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
6061 // the field and namespace allowing more extensibility for validators.
6162 GetStructFieldOKAdvanced2(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool, bool)
6263 }
106107 return current, kind, found
107108 }
108109
109 // GetStructFieldOK returns Param returns param for validation against current field
110 // GetStructFieldOK2 returns Param returns param for validation against current field
110111 func (v *validate) GetStructFieldOK2() (reflect.Value, reflect.Kind, bool, bool) {
111112 return v.getStructFieldOKInternal(v.slflParent, v.ct.param)
112113 }
113114
114 // GetStructFieldOKAdvanced is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
115 // GetStructFieldOKAdvanced2 is the same as GetStructFieldOK except that it accepts the parent struct to start looking for
115116 // the field and namespace allowing more extensibility for validators.
116117 func (v *validate) GetStructFieldOKAdvanced2(val reflect.Value, namespace string) (reflect.Value, reflect.Kind, bool, bool) {
117118 return v.getStructFieldOKInternal(val, namespace)
77 github.com/go-playground/universal-translator v0.17.0
88 github.com/leodido/go-urn v1.2.0
99 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
10 golang.org/x/text v0.3.2 // indirect
1011 )
99 github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
1010 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1111 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
12 github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
1213 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
1314 github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
1415 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
1516 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
1617 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
1718 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
19 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
1820 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
1921 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
22 golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
2023 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
2124 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
25 golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
2226 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
27 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
2328 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
2429 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
2530 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
0 package validator
1
2 import "regexp"
3
4 var postCodePatternDict = map[string]string{
5 "GB": `^GIR[ ]?0AA|((AB|AL|B|BA|BB|BD|BH|BL|BN|BR|BS|BT|CA|CB|CF|CH|CM|CO|CR|CT|CV|CW|DA|DD|DE|DG|DH|DL|DN|DT|DY|E|EC|EH|EN|EX|FK|FY|G|GL|GY|GU|HA|HD|HG|HP|HR|HS|HU|HX|IG|IM|IP|IV|JE|KA|KT|KW|KY|L|LA|LD|LE|LL|LN|LS|LU|M|ME|MK|ML|N|NE|NG|NN|NP|NR|NW|OL|OX|PA|PE|PH|PL|PO|PR|RG|RH|RM|S|SA|SE|SG|SK|SL|SM|SN|SO|SP|SR|SS|ST|SW|SY|TA|TD|TF|TN|TQ|TR|TS|TW|UB|W|WA|WC|WD|WF|WN|WR|WS|WV|YO|ZE)(\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}))|BFPO[ ]?\d{1,4}$`,
6 "JE": `^JE\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`,
7 "GG": `^GY\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`,
8 "IM": `^IM\d[\dA-Z]?[ ]?\d[ABD-HJLN-UW-Z]{2}$`,
9 "US": `^\d{5}([ \-]\d{4})?$`,
10 "CA": `^[ABCEGHJKLMNPRSTVXY]\d[ABCEGHJ-NPRSTV-Z][ ]?\d[ABCEGHJ-NPRSTV-Z]\d$`,
11 "DE": `^\d{5}$`,
12 "JP": `^\d{3}-\d{4}$`,
13 "FR": `^\d{2}[ ]?\d{3}$`,
14 "AU": `^\d{4}$`,
15 "IT": `^\d{5}$`,
16 "CH": `^\d{4}$`,
17 "AT": `^\d{4}$`,
18 "ES": `^\d{5}$`,
19 "NL": `^\d{4}[ ]?[A-Z]{2}$`,
20 "BE": `^\d{4}$`,
21 "DK": `^\d{4}$`,
22 "SE": `^\d{3}[ ]?\d{2}$`,
23 "NO": `^\d{4}$`,
24 "BR": `^\d{5}[\-]?\d{3}$`,
25 "PT": `^\d{4}([\-]\d{3})?$`,
26 "FI": `^\d{5}$`,
27 "AX": `^22\d{3}$`,
28 "KR": `^\d{3}[\-]\d{3}$`,
29 "CN": `^\d{6}$`,
30 "TW": `^\d{3}(\d{2})?$`,
31 "SG": `^\d{6}$`,
32 "DZ": `^\d{5}$`,
33 "AD": `^AD\d{3}$`,
34 "AR": `^([A-HJ-NP-Z])?\d{4}([A-Z]{3})?$`,
35 "AM": `^(37)?\d{4}$`,
36 "AZ": `^\d{4}$`,
37 "BH": `^((1[0-2]|[2-9])\d{2})?$`,
38 "BD": `^\d{4}$`,
39 "BB": `^(BB\d{5})?$`,
40 "BY": `^\d{6}$`,
41 "BM": `^[A-Z]{2}[ ]?[A-Z0-9]{2}$`,
42 "BA": `^\d{5}$`,
43 "IO": `^BBND 1ZZ$`,
44 "BN": `^[A-Z]{2}[ ]?\d{4}$`,
45 "BG": `^\d{4}$`,
46 "KH": `^\d{5}$`,
47 "CV": `^\d{4}$`,
48 "CL": `^\d{7}$`,
49 "CR": `^\d{4,5}|\d{3}-\d{4}$`,
50 "HR": `^\d{5}$`,
51 "CY": `^\d{4}$`,
52 "CZ": `^\d{3}[ ]?\d{2}$`,
53 "DO": `^\d{5}$`,
54 "EC": `^([A-Z]\d{4}[A-Z]|(?:[A-Z]{2})?\d{6})?$`,
55 "EG": `^\d{5}$`,
56 "EE": `^\d{5}$`,
57 "FO": `^\d{3}$`,
58 "GE": `^\d{4}$`,
59 "GR": `^\d{3}[ ]?\d{2}$`,
60 "GL": `^39\d{2}$`,
61 "GT": `^\d{5}$`,
62 "HT": `^\d{4}$`,
63 "HN": `^(?:\d{5})?$`,
64 "HU": `^\d{4}$`,
65 "IS": `^\d{3}$`,
66 "IN": `^\d{6}$`,
67 "ID": `^\d{5}$`,
68 "IL": `^\d{5}$`,
69 "JO": `^\d{5}$`,
70 "KZ": `^\d{6}$`,
71 "KE": `^\d{5}$`,
72 "KW": `^\d{5}$`,
73 "LA": `^\d{5}$`,
74 "LV": `^\d{4}$`,
75 "LB": `^(\d{4}([ ]?\d{4})?)?$`,
76 "LI": `^(948[5-9])|(949[0-7])$`,
77 "LT": `^\d{5}$`,
78 "LU": `^\d{4}$`,
79 "MK": `^\d{4}$`,
80 "MY": `^\d{5}$`,
81 "MV": `^\d{5}$`,
82 "MT": `^[A-Z]{3}[ ]?\d{2,4}$`,
83 "MU": `^(\d{3}[A-Z]{2}\d{3})?$`,
84 "MX": `^\d{5}$`,
85 "MD": `^\d{4}$`,
86 "MC": `^980\d{2}$`,
87 "MA": `^\d{5}$`,
88 "NP": `^\d{5}$`,
89 "NZ": `^\d{4}$`,
90 "NI": `^((\d{4}-)?\d{3}-\d{3}(-\d{1})?)?$`,
91 "NG": `^(\d{6})?$`,
92 "OM": `^(PC )?\d{3}$`,
93 "PK": `^\d{5}$`,
94 "PY": `^\d{4}$`,
95 "PH": `^\d{4}$`,
96 "PL": `^\d{2}-\d{3}$`,
97 "PR": `^00[679]\d{2}([ \-]\d{4})?$`,
98 "RO": `^\d{6}$`,
99 "RU": `^\d{6}$`,
100 "SM": `^4789\d$`,
101 "SA": `^\d{5}$`,
102 "SN": `^\d{5}$`,
103 "SK": `^\d{3}[ ]?\d{2}$`,
104 "SI": `^\d{4}$`,
105 "ZA": `^\d{4}$`,
106 "LK": `^\d{5}$`,
107 "TJ": `^\d{6}$`,
108 "TH": `^\d{5}$`,
109 "TN": `^\d{4}$`,
110 "TR": `^\d{5}$`,
111 "TM": `^\d{6}$`,
112 "UA": `^\d{5}$`,
113 "UY": `^\d{5}$`,
114 "UZ": `^\d{6}$`,
115 "VA": `^00120$`,
116 "VE": `^\d{4}$`,
117 "ZM": `^\d{5}$`,
118 "AS": `^96799$`,
119 "CC": `^6799$`,
120 "CK": `^\d{4}$`,
121 "RS": `^\d{6}$`,
122 "ME": `^8\d{4}$`,
123 "CS": `^\d{5}$`,
124 "YU": `^\d{5}$`,
125 "CX": `^6798$`,
126 "ET": `^\d{4}$`,
127 "FK": `^FIQQ 1ZZ$`,
128 "NF": `^2899$`,
129 "FM": `^(9694[1-4])([ \-]\d{4})?$`,
130 "GF": `^9[78]3\d{2}$`,
131 "GN": `^\d{3}$`,
132 "GP": `^9[78][01]\d{2}$`,
133 "GS": `^SIQQ 1ZZ$`,
134 "GU": `^969[123]\d([ \-]\d{4})?$`,
135 "GW": `^\d{4}$`,
136 "HM": `^\d{4}$`,
137 "IQ": `^\d{5}$`,
138 "KG": `^\d{6}$`,
139 "LR": `^\d{4}$`,
140 "LS": `^\d{3}$`,
141 "MG": `^\d{3}$`,
142 "MH": `^969[67]\d([ \-]\d{4})?$`,
143 "MN": `^\d{6}$`,
144 "MP": `^9695[012]([ \-]\d{4})?$`,
145 "MQ": `^9[78]2\d{2}$`,
146 "NC": `^988\d{2}$`,
147 "NE": `^\d{4}$`,
148 "VI": `^008(([0-4]\d)|(5[01]))([ \-]\d{4})?$`,
149 "VN": `^[0-9]{1,6}$`,
150 "PF": `^987\d{2}$`,
151 "PG": `^\d{3}$`,
152 "PM": `^9[78]5\d{2}$`,
153 "PN": `^PCRN 1ZZ$`,
154 "PW": `^96940$`,
155 "RE": `^9[78]4\d{2}$`,
156 "SH": `^(ASCN|STHL) 1ZZ$`,
157 "SJ": `^\d{4}$`,
158 "SO": `^\d{5}$`,
159 "SZ": `^[HLMS]\d{3}$`,
160 "TC": `^TKCA 1ZZ$`,
161 "WF": `^986\d{2}$`,
162 "XK": `^\d{5}$`,
163 "YT": `^976\d{2}$`,
164 }
165
166 var postCodeRegexDict = map[string]*regexp.Regexp{}
167
168 func init() {
169 for countryCode, pattern := range postCodePatternDict {
170 postCodeRegexDict[countryCode] = regexp.MustCompile(pattern)
171 }
172 }
99 numericRegexString = "^[-+]?[0-9]+(?:\\.[0-9]+)?$"
1010 numberRegexString = "^[0-9]+$"
1111 hexadecimalRegexString = "^(0[xX])?[0-9a-fA-F]+$"
12 hexcolorRegexString = "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
12 hexColorRegexString = "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
1313 rgbRegexString = "^rgb\\(\\s*(?:(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])|(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%)\\s*\\)$"
1414 rgbaRegexString = "^rgba\\(\\s*(?:(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])|(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%\\s*,\\s*(?:0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%)\\s*,\\s*(?:(?:0.[1-9]*)|[01])\\s*\\)$"
1515 hslRegexString = "^hsl\\(\\s*(?:0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d|360)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*,\\s*(?:(?:0|[1-9]\\d?|100)%)\\s*\\)$"
4444 ethAddressRegexString = `^0x[0-9a-fA-F]{40}$`
4545 ethAddressUpperRegexString = `^0x[0-9A-F]{40}$`
4646 ethAddressLowerRegexString = `^0x[0-9a-f]{40}$`
47 uRLEncodedRegexString = `(%[A-Fa-f0-9]{2})`
47 uRLEncodedRegexString = `^(?:[^%]|%[0-9A-Fa-f]{2})*$`
4848 hTMLEncodedRegexString = `&#[x]?([0-9a-fA-F]{2})|(&gt)|(&lt)|(&quot)|(&amp)+[;]?`
4949 hTMLRegexString = `<[/]?([a-zA-Z]+).*?>`
5050 splitParamsRegexString = `'[^']*'|\S+`
51 bicRegexString = `^[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?$`
5152 )
5253
5354 var (
5859 numericRegex = regexp.MustCompile(numericRegexString)
5960 numberRegex = regexp.MustCompile(numberRegexString)
6061 hexadecimalRegex = regexp.MustCompile(hexadecimalRegexString)
61 hexcolorRegex = regexp.MustCompile(hexcolorRegexString)
62 hexColorRegex = regexp.MustCompile(hexColorRegexString)
6263 rgbRegex = regexp.MustCompile(rgbRegexString)
6364 rgbaRegex = regexp.MustCompile(rgbaRegexString)
6465 hslRegex = regexp.MustCompile(hslRegexString)
9192 btcUpperAddressRegexBech32 = regexp.MustCompile(btcAddressUpperRegexStringBech32)
9293 btcLowerAddressRegexBech32 = regexp.MustCompile(btcAddressLowerRegexStringBech32)
9394 ethAddressRegex = regexp.MustCompile(ethAddressRegexString)
94 ethaddressRegexUpper = regexp.MustCompile(ethAddressUpperRegexString)
95 ethAddressRegexUpper = regexp.MustCompile(ethAddressUpperRegexString)
9596 ethAddressRegexLower = regexp.MustCompile(ethAddressLowerRegexString)
9697 uRLEncodedRegex = regexp.MustCompile(uRLEncodedRegexString)
9798 hTMLEncodedRegex = regexp.MustCompile(hTMLEncodedRegexString)
9899 hTMLRegex = regexp.MustCompile(hTMLRegexString)
99100 splitParamsRegex = regexp.MustCompile(splitParamsRegexString)
101 bicRegex = regexp.MustCompile(bicRegexString)
100102 )
2222 // to validate a struct
2323 type StructLevel interface {
2424
25 // returns the main validation object, in case one wants to call validations internally.
25 // Validator returns the main validation object, in case one wants to call validations internally.
2626 // this is so you don't have to use anonymous functions to get access to the validate
2727 // instance.
2828 Validator() *Validate
2929
30 // returns the top level struct, if any
30 // Top returns the top level struct, if any
3131 Top() reflect.Value
3232
33 // returns the current fields parent struct, if any
33 // Parent returns the current fields parent struct, if any
3434 Parent() reflect.Value
3535
36 // returns the current struct.
36 // Current returns the current struct.
3737 Current() reflect.Value
3838
3939 // ExtractType gets the actual underlying type of field value.
4141 // underlying value and its kind.
4242 ExtractType(field reflect.Value) (value reflect.Value, kind reflect.Kind, nullable bool)
4343
44 // reports an error just by passing the field and tag information
44 // ReportError reports an error just by passing the field and tag information
4545 //
4646 // NOTES:
4747 //
5353 // and process on the flip side it's up to you.
5454 ReportError(field interface{}, fieldName, structFieldName string, tag, param string)
5555
56 // reports an error just by passing ValidationErrors
56 // ReportValidationErrors reports an error just by passing ValidationErrors
5757 //
5858 // NOTES:
5959 //
1515 // RegisterDefaultTranslations registers a set of default translations
1616 // for all built in tag's in validator; you may add your own as desired.
1717 func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (err error) {
18
1918 translations := []struct {
2019 tag string
2120 translation string
3130 {
3231 tag: "len",
3332 customRegisFunc: func(ut ut.Translator) (err error) {
34
3533 if err = ut.Add("len-string", "{0} must be {1} in length", false); err != nil {
3634 return
3735 }
6058 }
6159
6260 return
63
64 },
65 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
66
61 },
62 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
6763 var err error
6864 var t string
6965
122118 {
123119 tag: "min",
124120 customRegisFunc: func(ut ut.Translator) (err error) {
125
126121 if err = ut.Add("min-string", "{0} must be at least {1} in length", false); err != nil {
127122 return
128123 }
151146 }
152147
153148 return
154
155 },
156 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
157
149 },
150 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
158151 var err error
159152 var t string
160153
213206 {
214207 tag: "max",
215208 customRegisFunc: func(ut ut.Translator) (err error) {
216
217209 if err = ut.Add("max-string", "{0} must be a maximum of {1} in length", false); err != nil {
218210 return
219211 }
242234 }
243235
244236 return
245
246 },
247 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
248
237 },
238 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
249239 var err error
250240 var t string
251241
306296 translation: "{0} is not equal to {1}",
307297 override: false,
308298 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
309
310299 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
311300 if err != nil {
312301 fmt.Printf("warning: error translating FieldError: %#v", fe)
321310 translation: "{0} should not be equal to {1}",
322311 override: false,
323312 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
324
325313 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
326314 if err != nil {
327315 fmt.Printf("warning: error translating FieldError: %#v", fe)
334322 {
335323 tag: "lt",
336324 customRegisFunc: func(ut ut.Translator) (err error) {
337
338325 if err = ut.Add("lt-string", "{0} must be less than {1} in length", false); err != nil {
339326 return
340327 }
368355 }
369356
370357 return
371
372 },
373 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
374
358 },
359 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
375360 var err error
376361 var t string
377362 var f64 float64
379364 var kind reflect.Kind
380365
381366 fn := func() (err error) {
382
383367 if idx := strings.Index(fe.Param(), "."); idx != -1 {
384368 digits = uint64(len(fe.Param()[idx+1:]))
385369 }
455439 {
456440 tag: "lte",
457441 customRegisFunc: func(ut ut.Translator) (err error) {
458
459442 if err = ut.Add("lte-string", "{0} must be at maximum {1} in length", false); err != nil {
460443 return
461444 }
491474 return
492475 },
493476 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
494
495477 var err error
496478 var t string
497479 var f64 float64
499481 var kind reflect.Kind
500482
501483 fn := func() (err error) {
502
503484 if idx := strings.Index(fe.Param(), "."); idx != -1 {
504485 digits = uint64(len(fe.Param()[idx+1:]))
505486 }
575556 {
576557 tag: "gt",
577558 customRegisFunc: func(ut ut.Translator) (err error) {
578
579559 if err = ut.Add("gt-string", "{0} must be greater than {1} in length", false); err != nil {
580560 return
581561 }
611591 return
612592 },
613593 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
614
615594 var err error
616595 var t string
617596 var f64 float64
619598 var kind reflect.Kind
620599
621600 fn := func() (err error) {
622
623601 if idx := strings.Index(fe.Param(), "."); idx != -1 {
624602 digits = uint64(len(fe.Param()[idx+1:]))
625603 }
695673 {
696674 tag: "gte",
697675 customRegisFunc: func(ut ut.Translator) (err error) {
698
699676 if err = ut.Add("gte-string", "{0} must be at least {1} in length", false); err != nil {
700677 return
701678 }
731708 return
732709 },
733710 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
734
735711 var err error
736712 var t string
737713 var f64 float64
739715 var kind reflect.Kind
740716
741717 fn := func() (err error) {
742
743718 if idx := strings.Index(fe.Param(), "."); idx != -1 {
744719 digits = uint64(len(fe.Param()[idx+1:]))
745720 }
817792 translation: "{0} must be equal to {1}",
818793 override: false,
819794 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
820
821795 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
822796 if err != nil {
823797 log.Printf("warning: error translating FieldError: %#v", fe)
832806 translation: "{0} must be equal to {1}",
833807 override: false,
834808 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
835
836809 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
837810 if err != nil {
838811 log.Printf("warning: error translating FieldError: %#v", fe)
847820 translation: "{0} cannot be equal to {1}",
848821 override: false,
849822 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
850
851823 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
852824 if err != nil {
853825 log.Printf("warning: error translating FieldError: %#v", fe)
862834 translation: "{0} must be greater than {1}",
863835 override: false,
864836 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
865
866837 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
867838 if err != nil {
868839 log.Printf("warning: error translating FieldError: %#v", fe)
877848 translation: "{0} must be greater than or equal to {1}",
878849 override: false,
879850 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
880
881851 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
882852 if err != nil {
883853 log.Printf("warning: error translating FieldError: %#v", fe)
892862 translation: "{0} must be less than {1}",
893863 override: false,
894864 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
895
896865 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
897866 if err != nil {
898867 log.Printf("warning: error translating FieldError: %#v", fe)
907876 translation: "{0} must be less than or equal to {1}",
908877 override: false,
909878 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
910
911879 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
912880 if err != nil {
913881 log.Printf("warning: error translating FieldError: %#v", fe)
922890 translation: "{0} cannot be equal to {1}",
923891 override: false,
924892 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
925
926893 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
927894 if err != nil {
928895 log.Printf("warning: error translating FieldError: %#v", fe)
937904 translation: "{0} must be greater than {1}",
938905 override: false,
939906 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
940
941907 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
942908 if err != nil {
943909 log.Printf("warning: error translating FieldError: %#v", fe)
952918 translation: "{0} must be greater than or equal to {1}",
953919 override: false,
954920 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
955
956921 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
957922 if err != nil {
958923 log.Printf("warning: error translating FieldError: %#v", fe)
967932 translation: "{0} must be less than {1}",
968933 override: false,
969934 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
970
971935 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
972936 if err != nil {
973937 log.Printf("warning: error translating FieldError: %#v", fe)
982946 translation: "{0} must be less than or equal to {1}",
983947 override: false,
984948 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
985
986949 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
987950 if err != nil {
988951 log.Printf("warning: error translating FieldError: %#v", fe)
10721035 translation: "{0} must contain the text '{1}'",
10731036 override: false,
10741037 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
1075
10761038 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
10771039 if err != nil {
10781040 log.Printf("warning: error translating FieldError: %#v", fe)
10871049 translation: "{0} must contain at least one of the following characters '{1}'",
10881050 override: false,
10891051 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
1090
10911052 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
10921053 if err != nil {
10931054 log.Printf("warning: error translating FieldError: %#v", fe)
11021063 translation: "{0} cannot contain the text '{1}'",
11031064 override: false,
11041065 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
1105
11061066 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
11071067 if err != nil {
11081068 log.Printf("warning: error translating FieldError: %#v", fe)
11171077 translation: "{0} cannot contain any of the following characters '{1}'",
11181078 override: false,
11191079 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
1120
11211080 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
11221081 if err != nil {
11231082 log.Printf("warning: error translating FieldError: %#v", fe)
11321091 translation: "{0} cannot contain the following '{1}'",
11331092 override: false,
11341093 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
1135
11361094 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
11371095 if err != nil {
11381096 log.Printf("warning: error translating FieldError: %#v", fe)
13241282 tag: "json",
13251283 translation: "{0} must be a valid json string",
13261284 override: false,
1327 },
1328 {
1285 },
1286 {
13291287 tag: "lowercase",
13301288 translation: "{0} must be a lowercase string",
13311289 override: false,
13401298 translation: "{0} does not match the {1} format",
13411299 override: false,
13421300 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
1343
1301 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
1302 if err != nil {
1303 log.Printf("warning: error translating FieldError: %#v", fe)
1304 return fe.(error).Error()
1305 }
1306
1307 return t
1308 },
1309 },
1310 {
1311 tag: "postcode_iso3166_alpha2",
1312 translation: "{0} does not match postcode format of {1} country",
1313 override: false,
1314 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
1315 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
1316 if err != nil {
1317 log.Printf("warning: error translating FieldError: %#v", fe)
1318 return fe.(error).Error()
1319 }
1320
1321 return t
1322 },
1323 },
1324 {
1325 tag: "postcode_iso3166_alpha2_field",
1326 translation: "{0} does not match postcode format of country in {1} field",
1327 override: false,
1328 customTransFunc: func(ut ut.Translator, fe validator.FieldError) string {
13441329 t, err := ut.T(fe.Tag(), fe.Field(), fe.Param())
13451330 if err != nil {
13461331 log.Printf("warning: error translating FieldError: %#v", fe)
13551340 for _, t := range translations {
13561341
13571342 if t.customTransFunc != nil && t.customRegisFunc != nil {
1358
13591343 err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, t.customTransFunc)
1360
13611344 } else if t.customTransFunc != nil && t.customRegisFunc == nil {
1362
13631345 err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), t.customTransFunc)
1364
13651346 } else if t.customTransFunc == nil && t.customRegisFunc != nil {
1366
13671347 err = v.RegisterTranslation(t.tag, trans, t.customRegisFunc, translateFunc)
1368
13691348 } else {
13701349 err = v.RegisterTranslation(t.tag, trans, registrationFunc(t.tag, t.translation, t.override), translateFunc)
13711350 }
13791358 }
13801359
13811360 func registrationFunc(tag string, translation string, override bool) validator.RegisterTranslationsFunc {
1382
13831361 return func(ut ut.Translator) (err error) {
1384
13851362 if err = ut.Add(tag, translation, override); err != nil {
13861363 return
13871364 }
13881365
13891366 return
1390
13911367 }
1392
13931368 }
13941369
13951370 func translateFunc(ut ut.Translator, fe validator.FieldError) string {
1396
13971371 t, err := ut.T(fe.Tag(), fe.Field())
13981372 if err != nil {
13991373 log.Printf("warning: error translating FieldError: %#v", fe)
1010 )
1111
1212 func TestTranslations(t *testing.T) {
13
1413 eng := english.New()
1514 uni := ut.New(eng, eng)
1615 trans, _ := uni.GetTranslator("en")
144143 LowercaseString string `validate:"lowercase"`
145144 UppercaseString string `validate:"uppercase"`
146145 Datetime string `validate:"datetime=2006-01-02"`
146 PostCode string `validate:"postcode_iso3166_alpha2=SG"`
147 PostCodeCountry string
148 PostCodeByField string `validate:"postcode_iso3166_alpha2_field=PostCodeCountry"`
147149 }
148150
149151 var test Test
654656 {
655657 ns: "Test.Datetime",
656658 expected: "Datetime does not match the 2006-01-02 format",
659 },
660 {
661 ns: "Test.PostCode",
662 expected: "PostCode does not match postcode format of SG country",
663 },
664 {
665 ns: "Test.PostCodeByField",
666 expected: "PostCodeByField does not match postcode format of country in PostCodeCountry field",
657667 },
658668 }
659669
671681 NotEqual(t, fe, nil)
672682 Equal(t, tt.expected, fe.Translate(trans))
673683 }
674
675684 }
7373 }
7474 }
7575
76 v.traverseField(ctx, parent, current.Field(f.idx), ns, structNs, f, f.cTags)
76 v.traverseField(ctx, current, current.Field(f.idx), ns, structNs, f, f.cTags)
7777 }
7878 }
7979
221221 structNs = append(append(structNs, cf.name...), '.')
222222 }
223223
224 v.validateStruct(ctx, current, current, typ, ns, structNs, ct)
224 v.validateStruct(ctx, parent, current, typ, ns, structNs, ct)
225225 return
226226 }
227227 }
2828 requiredWithAllTag = "required_with_all"
2929 requiredIfTag = "required_if"
3030 requiredUnlessTag = "required_unless"
31 excludedWithoutAllTag = "excluded_without_all"
32 excludedWithoutTag = "excluded_without"
33 excludedWithTag = "excluded_with"
34 excludedWithAllTag = "excluded_with_all"
3135 skipValidationTag = "-"
3236 diveTag = "dive"
3337 keysTag = "keys"
110114
111115 switch k {
112116 // these require that even if the value is nil that the validation should run, omitempty still overrides this behaviour
113 case requiredIfTag, requiredUnlessTag, requiredWithTag, requiredWithAllTag, requiredWithoutTag, requiredWithoutAllTag:
117 case requiredIfTag, requiredUnlessTag, requiredWithTag, requiredWithAllTag, requiredWithoutTag, requiredWithoutAllTag,
118 excludedWithTag, excludedWithAllTag, excludedWithoutTag, excludedWithoutAllTag:
114119 _ = v.registerValidation(k, wrapFunc(val), true, true)
115120 default:
116121 // no need to error check here, baked in will always be valid
135140 // SetTagName allows for changing of the default tag name of 'validate'
136141 func (v *Validate) SetTagName(name string) {
137142 v.tagName = name
143 }
144
145 // ValidateMapCtx validates a map using a map of validation rules and allows passing of contextual
146 // validation validation information via context.Context.
147 func (v Validate) ValidateMapCtx(ctx context.Context, data map[string]interface{}, rules map[string]interface{}) map[string]interface{} {
148 errs := make(map[string]interface{})
149 for field, rule := range rules {
150 if reflect.ValueOf(rule).Kind() == reflect.Map && reflect.ValueOf(data[field]).Kind() == reflect.Map {
151 err := v.ValidateMapCtx(ctx, data[field].(map[string]interface{}), rule.(map[string]interface{}))
152 if len(err) > 0 {
153 errs[field] = err
154 }
155 } else if reflect.ValueOf(rule).Kind() == reflect.Map {
156 errs[field] = errors.New("The field: '" + field + "' is not a map to dive")
157 } else {
158 err := v.VarCtx(ctx, data[field], rule.(string))
159 if err != nil {
160 errs[field] = err
161 }
162 }
163 }
164 return errs
165 }
166
167 // ValidateMap validates map data form a map of tags
168 func (v *Validate) ValidateMap(data map[string]interface{}, rules map[string]interface{}) map[string]interface{} {
169 return v.ValidateMapCtx(context.Background(), data, rules)
138170 }
139171
140172 // RegisterTagNameFunc registers a function to get alternate names for StructFields.
408440 if len(flds) > 0 {
409441
410442 vd.misc = append(vd.misc[0:0], name...)
411 vd.misc = append(vd.misc, '.')
443 // Don't append empty name for unnamed structs
444 if len(vd.misc) != 0 {
445 vd.misc = append(vd.misc, '.')
446 }
412447
413448 for _, s := range flds {
414449
1313 "testing"
1414 "time"
1515
16 "github.com/go-playground/assert/v2"
1617 . "github.com/go-playground/assert/v2"
1718 "github.com/go-playground/locales/en"
1819 "github.com/go-playground/locales/fr"
107108 }
108109
109110 func AssertError(t *testing.T, err error, nsKey, structNsKey, field, structField, expectedTag string) {
110
111111 errs := err.(ValidationErrors)
112112
113113 found := false
149149 }
150150
151151 func getError(err error, nsKey, structNsKey string) FieldError {
152
153152 errs := err.(ValidationErrors)
154153
155154 var fe FieldError
169168 }
170169
171170 func (v valuer) Value() (driver.Value, error) {
172
173171 if v.Name == "errorme" {
174172 panic("SQL Driver Valuer error: some kind of error")
175173 // return nil, errors.New("some kind of error")
188186 }
189187
190188 func ValidateCustomType(field reflect.Value) interface{} {
191
192189 if cust, ok := field.Interface().(MadeUpCustomType); ok {
193190
194191 if len(cust.FirstName) == 0 || len(cust.LastName) == 0 {
202199 }
203200
204201 func OverrideIntTypeForSomeReason(field reflect.Value) interface{} {
205
206202 if i, ok := field.Interface().(int); ok {
207203 if i == 1 {
208204 return "1"
222218 }
223219
224220 func ValidateValuerType(field reflect.Value) interface{} {
225
226221 if valuer, ok := field.Interface().(driver.Valuer); ok {
227222
228223 val, err := valuer.Value()
260255 }
261256
262257 func StructValidationTestStructSuccess(sl StructLevel) {
263
264258 st := sl.Current().Interface().(TestStruct)
265259
266260 if st.String != "good value" {
269263 }
270264
271265 func StructValidationTestStruct(sl StructLevel) {
272
273266 st := sl.Current().Interface().(TestStruct)
274267
275268 if st.String != "bad value" {
278271 }
279272
280273 func StructValidationNoTestStructCustomName(sl StructLevel) {
281
282274 st := sl.Current().Interface().(TestStruct)
283275
284276 if st.String != "bad value" {
287279 }
288280
289281 func StructValidationTestStructInvalid(sl StructLevel) {
290
291282 st := sl.Current().Interface().(TestStruct)
292283
293284 if st.String != "bad value" {
296287 }
297288
298289 func StructValidationTestStructReturnValidationErrors(sl StructLevel) {
299
300290 s := sl.Current().Interface().(TestStructReturnValidationErrors)
301291
302292 errs := sl.Validator().Struct(s.Inner1.Inner2)
308298 }
309299
310300 func StructValidationTestStructReturnValidationErrors2(sl StructLevel) {
311
312301 s := sl.Current().Interface().(TestStructReturnValidationErrors)
313302
314303 errs := sl.Validator().Struct(s.Inner1.Inner2)
336325 }
337326
338327 func StructLevelInvalidError(sl StructLevel) {
339
340328 top := sl.Top().Interface().(StructLevelInvalidErr)
341329 s := sl.Current().Interface().(StructLevelInvalidErr)
342330
358346 }
359347
360348 func TestStructLevelInvalidError(t *testing.T) {
361
362349 validate := New()
363350 validate.RegisterStructValidation(StructLevelInvalidError, StructLevelInvalidErr{})
364351
382369 }
383370
384371 func TestNameNamespace(t *testing.T) {
385
386372 type Inner2Namespace struct {
387373 String []string `validate:"dive,required" json:"JSONString"`
388374 }
431417 }
432418
433419 func TestAnonymous(t *testing.T) {
434
435420 validate := New()
436421 validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
437422 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
499484 }
500485
501486 func TestAnonymousSameStructDifferentTags(t *testing.T) {
502
503487 validate := New()
504488 validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
505489 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
544528 }
545529
546530 func TestStructLevelReturnValidationErrors(t *testing.T) {
547
548531 validate := New()
549532 validate.RegisterStructValidation(StructValidationTestStructReturnValidationErrors, TestStructReturnValidationErrors{})
550533
574557 }
575558
576559 func TestStructLevelReturnValidationErrorsWithJSON(t *testing.T) {
577
578560 validate := New()
579561 validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
580562 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
631613 }
632614
633615 func TestStructLevelValidations(t *testing.T) {
634
635616 v1 := New()
636617 v1.RegisterStructValidation(StructValidationTestStruct, TestStruct{})
637618
665646 }
666647
667648 func TestAliasTags(t *testing.T) {
668
669649 validate := New()
670650 validate.RegisterAlias("iscoloralias", "hexcolor|rgb|rgba|hsl|hsla")
671651
713693 }
714694
715695 func TestNilValidator(t *testing.T) {
716
717696 type TestStruct struct {
718697 Test string `validate:"required"`
719698 }
723702 var val *Validate
724703
725704 fn := func(fl FieldLevel) bool {
726
727705 return fl.Parent().String() == fl.Field().String()
728706 }
729707
948926 NotEqual(t, errs, nil)
949927 AssertError(t, errs, "TestPartial.Anonymous.SubAnonStruct[0].Test", "TestPartial.Anonymous.SubAnonStruct[0].Test", "Test", "Test", "required")
950928
929 // Test for unnamed struct
930 testStruct := &TestStruct{
931 String: "test",
932 }
933 unnamedStruct := struct {
934 String string `validate:"required" json:"StringVal"`
935 }{String: "test"}
936 composedUnnamedStruct := struct{ *TestStruct }{&TestStruct{String: "test"}}
937
938 errs = validate.StructPartial(testStruct, "String")
939 Equal(t, errs, nil)
940
941 errs = validate.StructPartial(unnamedStruct, "String")
942 Equal(t, errs, nil)
943
944 errs = validate.StructPartial(composedUnnamedStruct, "TestStruct.String")
945 Equal(t, errs, nil)
946
947 testStruct.String = ""
948 errs = validate.StructPartial(testStruct, "String")
949 NotEqual(t, errs, nil)
950 AssertError(t, errs, "TestStruct.String", "TestStruct.String", "String", "String", "required")
951
952 unnamedStruct.String = ""
953 errs = validate.StructPartial(unnamedStruct, "String")
954 NotEqual(t, errs, nil)
955 AssertError(t, errs, "String", "String", "String", "String", "required")
956
957 composedUnnamedStruct.String = ""
958 errs = validate.StructPartial(composedUnnamedStruct, "TestStruct.String")
959 NotEqual(t, errs, nil)
960 AssertError(t, errs, "TestStruct.String", "TestStruct.String", "String", "String", "required")
951961 }
952962
953963 func TestCrossStructLteFieldValidation(t *testing.T) {
16371647 i := 1
16381648 j = 1
16391649 k = 1.543
1650 b := true
16401651 arr := []string{"test"}
16411652
16421653 s2 := "abcd"
16431654 i2 := 1
16441655 j2 = 1
16451656 k2 = 1.543
1657 b2 := true
16461658 arr2 := []string{"test"}
16471659 arr3 := []string{"test", "test2"}
16481660 now2 := now
16631675 NotEqual(t, errs, nil)
16641676 AssertError(t, errs, "", "", "", "", "necsfield")
16651677
1678 errs = validate.VarWithValue(b2, b, "necsfield")
1679 NotEqual(t, errs, nil)
1680 AssertError(t, errs, "", "", "", "", "necsfield")
1681
16661682 errs = validate.VarWithValue(arr2, arr, "necsfield")
16671683 NotEqual(t, errs, nil)
16681684 AssertError(t, errs, "", "", "", "", "necsfield")
17881804 errs = validate.Struct(test)
17891805 Equal(t, errs, nil)
17901806
1791 newTime := time.Now().UTC()
1807 newTime := time.Now().Add(time.Hour).UTC()
17921808 test.CreatedAt = &newTime
17931809
17941810 errs = validate.Struct(test)
18011817 i := 1
18021818 j = 1
18031819 k = 1.543
1820 b := true
18041821 arr := []string{"test"}
18051822
18061823 var j2 uint64
18091826 i2 := 1
18101827 j2 = 1
18111828 k2 = 1.543
1829 b2 := true
18121830 arr2 := []string{"test"}
18131831 arr3 := []string{"test", "test2"}
18141832 now2 := now
18251843 errs = validate.VarWithValue(k2, k, "eqcsfield")
18261844 Equal(t, errs, nil)
18271845
1846 errs = validate.VarWithValue(b2, b, "eqcsfield")
1847 Equal(t, errs, nil)
1848
18281849 errs = validate.VarWithValue(arr2, arr, "eqcsfield")
18291850 Equal(t, errs, nil)
18301851
19271948 }
19281949
19291950 func TestCrossNamespaceFieldValidation(t *testing.T) {
1930
19311951 type SliceStruct struct {
19321952 Name string
19331953 }
21652185 }
21662186
21672187 func TestExistsValidation(t *testing.T) {
2168
21692188 jsonText := "{ \"truthiness2\": true }"
21702189
21712190 type Thing struct {
21962215 }
21972216
21982217 func TestSQLValue2Validation(t *testing.T) {
2199
22002218 validate := New()
22012219 validate.RegisterCustomTypeFunc(ValidateValuerType, valuer{}, (*driver.Valuer)(nil), sql.NullString{}, sql.NullInt64{}, sql.NullBool{}, sql.NullFloat64{})
22022220 validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
22472265 }
22482266
22492267 func TestSQLValueValidation(t *testing.T) {
2250
22512268 validate := New()
22522269 validate.RegisterCustomTypeFunc(ValidateValuerType, (*driver.Valuer)(nil), valuer{})
22532270 validate.RegisterCustomTypeFunc(ValidateCustomType, MadeUpCustomType{})
29252942 }
29262943
29272944 func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) {
2928
29292945 validate := New()
29302946
29312947 var m map[string]string
30033019 }
30043020
30053021 func TestDatePtrValidationIssueValidation(t *testing.T) {
3006
30073022 type Test struct {
30083023 LastViewed *time.Time
30093024 Reminder *time.Time
30553070 }
30563071
30573072 func TestInterfaceErrValidation(t *testing.T) {
3058
30593073 var v2 interface{} = 1
30603074 var v1 interface{} = v2
30613075
32293243 }
32303244
32313245 func TestMapDiveValidation(t *testing.T) {
3232
32333246 validate := New()
32343247
32353248 n := map[int]interface{}{0: nil}
33523365 }
33533366
33543367 func TestArrayDiveValidation(t *testing.T) {
3355
33563368 validate := New()
33573369
33583370 arr := []string{"ok", "", "ok"}
43614373 }
43624374
43634375 func TestExcludesRuneValidation(t *testing.T) {
4364
43654376 tests := []struct {
43664377 Value string `validate:"excludesrune=☻"`
43674378 Tag string
43894400 }
43904401
43914402 func TestExcludesAllValidation(t *testing.T) {
4392
43934403 tests := []struct {
43944404 Value string `validate:"excludesall=@!{}[]"`
43954405 Tag string
44354445 }
44364446
44374447 func TestExcludesValidation(t *testing.T) {
4438
44394448 tests := []struct {
44404449 Value string `validate:"excludes=@"`
44414450 Tag string
44634472 }
44644473
44654474 func TestContainsRuneValidation(t *testing.T) {
4466
44674475 tests := []struct {
44684476 Value string `validate:"containsrune=☻"`
44694477 Tag string
44914499 }
44924500
44934501 func TestContainsAnyValidation(t *testing.T) {
4494
44954502 tests := []struct {
44964503 Value string `validate:"containsany=@!{}[]"`
44974504 Tag string
45194526 }
45204527
45214528 func TestContainsValidation(t *testing.T) {
4522
45234529 tests := []struct {
45244530 Value string `validate:"contains=@"`
45254531 Tag string
45564562 i := 1
45574563 j = 1
45584564 k = 1.543
4565 b := true
45594566 arr := []string{"test"}
45604567 now := time.Now().UTC()
45614568
45654572 i2 := 3
45664573 j2 = 2
45674574 k2 = 1.5434456
4575 b2 := false
45684576 arr2 := []string{"test", "test2"}
45694577 arr3 := []string{"test"}
45704578 now2 := now
45814589 errs = validate.VarWithValue(k2, k, "nefield")
45824590 Equal(t, errs, nil)
45834591
4592 errs = validate.VarWithValue(b2, b, "nefield")
4593 Equal(t, errs, nil)
4594
45844595 errs = validate.VarWithValue(arr2, arr, "nefield")
45854596 Equal(t, errs, nil)
45864597
46064617 NotEqual(t, errs, nil)
46074618 AssertError(t, errs, "Test.Start", "Test.Start", "Start", "Start", "nefield")
46084619
4609 now3 := time.Now().UTC()
4620 now3 := time.Now().Add(time.Hour).UTC()
46104621
46114622 sv = &Test{
46124623 Start: &now,
47914802 i := 1
47924803 j = 1
47934804 k = 1.543
4805 b := true
47944806 arr := []string{"test"}
47954807 now := time.Now().UTC()
47964808
48004812 i2 := 1
48014813 j2 = 1
48024814 k2 = 1.543
4815 b2 := true
48034816 arr2 := []string{"test"}
48044817 arr3 := []string{"test", "test2"}
48054818 now2 := now
48164829 errs = validate.VarWithValue(k2, k, "eqfield")
48174830 Equal(t, errs, nil)
48184831
4832 errs = validate.VarWithValue(b2, b, "eqfield")
4833 Equal(t, errs, nil)
4834
48194835 errs = validate.VarWithValue(arr2, arr, "eqfield")
48204836 Equal(t, errs, nil)
48214837
48394855 errs = validate.Struct(sv)
48404856 Equal(t, errs, nil)
48414857
4842 now3 := time.Now().UTC()
4858 now3 := time.Now().Add(time.Hour).UTC()
48434859
48444860 sv = &Test{
48454861 Start: &now,
50955111 }
50965112
50975113 func TestBase64Validation(t *testing.T) {
5098
50995114 validate := New()
51005115
51015116 s := "dW5pY29ybg=="
51995214 }
52005215
52015216 func TestEthereumAddressValidation(t *testing.T) {
5202
52035217 validate := New()
52045218
52055219 tests := []struct {
52535267 }
52545268
52555269 func TestBitcoinAddressValidation(t *testing.T) {
5256
52575270 validate := New()
52585271
52595272 tests := []struct {
53635376 }
53645377
53655378 func TestBitcoinBech32AddressValidation(t *testing.T) {
5366
53675379 validate := New()
53685380
53695381 tests := []struct {
54145426 }
54155427
54165428 func TestNoStructLevelValidation(t *testing.T) {
5417
54185429 type Inner struct {
54195430 Test string `validate:"len=5"`
54205431 }
54465457 }
54475458
54485459 func TestStructOnlyValidation(t *testing.T) {
5449
54505460 type Inner struct {
54515461 Test string `validate:"len=5"`
54525462 }
65126522 Equal(t, errs, nil)
65136523
65146524 fn := func(fl FieldLevel) bool {
6515
65166525 return fl.Parent().String() == fl.Field().String()
65176526 }
65186527
65306539 }
65316540
65326541 func TestAddFunctions(t *testing.T) {
6533
65346542 fn := func(fl FieldLevel) bool {
6535
65366543 return true
65376544 }
65386545
65616568 }
65626569
65636570 func TestChangeTag(t *testing.T) {
6564
65656571 validate := New()
65666572 validate.SetTagName("val")
65676573
72087214 }
72097215
72107216 func TestUrnRFC2141(t *testing.T) {
7211
7212 var tests = []struct {
7217 tests := []struct {
72137218 param string
72147219 expected bool
72157220 }{
72857290 }
72867291
72877292 func TestUrl(t *testing.T) {
7288
7289 var tests = []struct {
7293 tests := []struct {
72907294 param string
72917295 expected bool
72927296 }{
73537357 }
73547358
73557359 func TestUri(t *testing.T) {
7356
7357 var tests = []struct {
7360 tests := []struct {
73587361 param string
73597362 expected bool
73607363 }{
74207423 }
74217424
74227425 func TestOrTag(t *testing.T) {
7423
74247426 validate := New()
74257427
74267428 s := "rgba(0,31,255,0.5)"
74507452 Equal(t, errs, nil)
74517453
74527454 s = "green"
7453 errs = validate.Var(s, "eq=|eq=blue,rgb|rgba") //should fail on first validation block
7455 errs = validate.Var(s, "eq=|eq=blue,rgb|rgba") // should fail on first validation block
74547456 NotEqual(t, errs, nil)
74557457 ve := errs.(ValidationErrors)
74567458 Equal(t, len(ve), 1)
74637465
74647466 v2 := New()
74657467 v2.RegisterTagNameFunc(func(fld reflect.StructField) string {
7466
74677468 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
74687469
74697470 if name == "-" {
74887489 }
74897490
74907491 func TestHsla(t *testing.T) {
7491
74927492 validate := New()
74937493
74947494 s := "hsla(360,100%,100%,1)"
75357535 }
75367536
75377537 func TestHsl(t *testing.T) {
7538
75397538 validate := New()
75407539
75417540 s := "hsl(360,100%,50%)"
75737572 }
75747573
75757574 func TestRgba(t *testing.T) {
7576
75777575 validate := New()
75787576
75797577 s := "rgba(0,31,255,0.5)"
76197617 }
76207618
76217619 func TestRgb(t *testing.T) {
7622
76237620 validate := New()
76247621
76257622 s := "rgb(0,31,255)"
76617658 }
76627659
76637660 func TestEmail(t *testing.T) {
7664
76657661 validate := New()
76667662
76677663 s := "test@mail.com"
77297725 }
77307726
77317727 func TestHexColor(t *testing.T) {
7732
77337728 validate := New()
77347729
77357730 s := "#fff"
77577752 }
77587753
77597754 func TestHexadecimal(t *testing.T) {
7760
77617755 validate := New()
77627756
77637757 s := "ff0044"
77847778 }
77857779
77867780 func TestNumber(t *testing.T) {
7787
77887781 validate := New()
77897782
77907783 s := "1"
78327825 }
78337826
78347827 func TestNumeric(t *testing.T) {
7835
78367828 validate := New()
78377829
78387830 s := "1"
78757867 }
78767868
78777869 func TestAlphaNumeric(t *testing.T) {
7878
78797870 validate := New()
78807871
78817872 s := "abcd123"
78937884 }
78947885
78957886 func TestAlpha(t *testing.T) {
7896
78977887 validate := New()
78987888
78997889 s := "abcd"
79237913 errs = validate.Var(1, "alpha")
79247914 NotEqual(t, errs, nil)
79257915 AssertError(t, errs, "", "", "", "", "alpha")
7926
79277916 }
79287917
79297918 func TestStructStringValidation(t *testing.T) {
7930
79317919 validate := New()
79327920
79337921 tSuccess := &TestString{
80097997 }
80107998
80117999 func TestStructInt32Validation(t *testing.T) {
8012
80138000 type TestInt32 struct {
80148001 Required int `validate:"required"`
80158002 Len int `validate:"len=10"`
80738060 }
80748061
80758062 func TestStructUint64Validation(t *testing.T) {
8076
80778063 validate := New()
80788064
80798065 tSuccess := &TestUint64{
81138099 }
81148100
81158101 func TestStructFloat64Validation(t *testing.T) {
8116
81178102 validate := New()
81188103
81198104 tSuccess := &TestFloat64{
81538138 }
81548139
81558140 func TestStructSliceValidation(t *testing.T) {
8156
81578141 validate := New()
81588142
81598143 tSuccess := &TestSlice{
82038187
82048188 _, ok := fe.Value().([]int)
82058189 Equal(t, ok, true)
8206
82078190 }
82088191
82098192 func TestInvalidStruct(t *testing.T) {
8210
82118193 validate := New()
82128194
82138195 s := &SubTest{
82328214 }
82338215
82348216 func TestInvalidValidatorFunction(t *testing.T) {
8235
82368217 validate := New()
82378218
82388219 s := &SubTest{
82438224 }
82448225
82458226 func TestCustomFieldName(t *testing.T) {
8246
82478227 validate := New()
82488228 validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
82498229 name := strings.SplitN(fld.Tag.Get("schema"), ",", 2)[0]
82878267 }
82888268
82898269 func TestMutipleRecursiveExtractStructCache(t *testing.T) {
8290
82918270 validate := New()
82928271
82938272 type Recursive struct {
83048283 ptr := fmt.Sprintf("%p", sc)
83058284
83068285 for i := 0; i < 100; i++ {
8307
83088286 go func() {
83098287 <-proceed
83108288 sc := validate.extractStructCache(current, name)
83178295
83188296 // Thanks @robbrockbank, see https://github.com/go-playground/validator/issues/249
83198297 func TestPointerAndOmitEmpty(t *testing.T) {
8320
83218298 validate := New()
83228299
83238300 type Test struct {
83638340 }
83648341
83658342 func TestRequired(t *testing.T) {
8366
83678343 validate := New()
83688344 validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
83698345 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
83878363 }
83888364
83898365 func TestBoolEqual(t *testing.T) {
8390
83918366 validate := New()
83928367
83938368 type Test struct {
84158390 validate := New()
84168391 err := validate.RegisterTranslation("required", trans,
84178392 func(ut ut.Translator) (err error) {
8418
84198393 // using this stype because multiple translation may have to be added for the full translation
84208394 if err = ut.Add("required", "{0} is a required field", false); err != nil {
84218395 return
84228396 }
84238397
84248398 return
8425
84268399 }, func(ut ut.Translator, fe FieldError) string {
8427
84288400 t, err := ut.T(fe.Tag(), fe.Field())
84298401 if err != nil {
84308402 fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError))
84378409
84388410 err = validate.RegisterTranslation("required", fr,
84398411 func(ut ut.Translator) (err error) {
8440
84418412 // using this stype because multiple translation may have to be added for the full translation
84428413 if err = ut.Add("required", "{0} est un champ obligatoire", false); err != nil {
84438414 return
84448415 }
84458416
84468417 return
8447
84488418 }, func(ut ut.Translator, fe FieldError) string {
8449
84508419 t, transErr := ut.T(fe.Tag(), fe.Field())
84518420 if transErr != nil {
84528421 fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError))
85248493 validate := New()
85258494 err = validate.RegisterTranslation("required", trans,
85268495 func(ut ut.Translator) (err error) {
8527
85288496 // using this stype because multiple translation may have to be added for the full translation
85298497 if err = ut.Add("required", "{0} is a required field", false); err != nil {
85308498 return
85318499 }
85328500
85338501 return
8534
85358502 }, func(ut ut.Translator, fe FieldError) string {
8536
85378503 t, err := ut.T(fe.Tag(), fe.Field())
85388504 if err != nil {
85398505 fmt.Printf("warning: error translating FieldError: %#v", fe.(*fieldError))
85488514 }
85498515
85508516 func TestStructFiltered(t *testing.T) {
8551
85528517 p1 := func(ns []byte) bool {
85538518 if bytes.HasSuffix(ns, []byte("NoTag")) || bytes.HasSuffix(ns, []byte("Required")) {
85548519 return false
87148679 }
87158680
87168681 func TestRequiredPtr(t *testing.T) {
8717
87188682 type Test struct {
87198683 Bool *bool `validate:"required"`
87208684 }
88488812 }
88498813
88508814 func TestAlphanumericUnicodeValidation(t *testing.T) {
8851
88528815 tests := []struct {
88538816 param string
88548817 expected bool
88918854 }
88928855
88938856 func TestArrayStructNamespace(t *testing.T) {
8894
88958857 validate := New()
88968858 validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
88978859 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
89208882 }
89218883
89228884 func TestMapStructNamespace(t *testing.T) {
8923
89248885 validate := New()
89258886 validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
89268887 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
95759536 {"a%b", false},
95769537 {"1%2", false},
95779538 {"%%a%%", false},
9539 {"hello", true},
9540 {"", true},
9541 {"+", true},
95789542 }
95799543
95809544 validate := New()
96019565 }
96029566
96039567 func TestKeys(t *testing.T) {
9604
96059568 type Test struct {
96069569 Test1 map[string]string `validate:"gt=0,dive,keys,eq=testkey,endkeys,eq=testval" json:"test1"`
96079570 Test2 map[int]int `validate:"gt=0,dive,keys,eq=3,endkeys,eq=4" json:"test2"`
97709733 }
97719734
97729735 func TestKeyOrs(t *testing.T) {
9773
97749736 type Test struct {
97759737 Test1 map[string]string `validate:"gt=0,dive,keys,eq=testkey|eq=testkeyok,endkeys,eq=testval" json:"test1"`
97769738 }
100279989 Field6 uint `validate:"required_unless=Field5 2" json:"field_6"`
100289990 Field7 float32 `validate:"required_unless=Field6 0" json:"field_7"`
100299991 Field8 float64 `validate:"required_unless=Field7 0.0" json:"field_8"`
9992 Field9 bool `validate:"omitempty" json:"field_9"`
9993 Field10 string `validate:"required_unless=Field9 true" json:"field_10"`
100309994 }{
100319995 FieldE: "test",
100329996 Field2: &fieldVal,
100339997 Field3: map[string]string{"key": "val"},
100349998 Field4: "test",
100359999 Field5: 2,
10000 Field9: true,
1003610001 }
1003710002
1003810003 validate := New()
1005210017 Field5 string `validate:"required_unless=Field3 0" json:"field_5"`
1005310018 Field6 string `validate:"required_unless=Inner.Field test" json:"field_6"`
1005410019 Field7 string `validate:"required_unless=Inner2.Field test" json:"field_7"`
10020 Field8 bool `validate:"omitempty" json:"field_8"`
10021 Field9 string `validate:"required_unless=Field8 true" json:"field_9"`
1005510022 }{
1005610023 Inner: &Inner{Field: &fieldVal},
1005710024 FieldE: "test",
1006210029 NotEqual(t, errs, nil)
1006310030
1006410031 ve := errs.(ValidationErrors)
10065 Equal(t, len(ve), 3)
10032 Equal(t, len(ve), 4)
1006610033 AssertError(t, errs, "Field3", "Field3", "Field3", "Field3", "required_unless")
1006710034 AssertError(t, errs, "Field4", "Field4", "Field4", "Field4", "required_unless")
1006810035 AssertError(t, errs, "Field7", "Field7", "Field7", "Field7", "required_unless")
10036 AssertError(t, errs, "Field9", "Field9", "Field9", "Field9", "required_unless")
1006910037
1007010038 defer func() {
1007110039 if r := recover(); r == nil {
1020110169 name := fmt.Sprintf("Field%d", i)
1020210170 AssertError(t, errs, name, name, name, name, "excluded_with")
1020310171 }
10172
10173 test3 := struct {
10174 Inner *Inner
10175 Inner2 *Inner
10176 Field string `validate:"omitempty" json:"field"`
10177 FieldE string `validate:"omitempty" json:"field_e"`
10178 Field1 string `validate:"excluded_with=FieldE" json:"field_1"`
10179 Field2 *string `validate:"excluded_with=FieldE" json:"field_2"`
10180 Field3 map[string]string `validate:"excluded_with=FieldE" json:"field_3"`
10181 Field4 interface{} `validate:"excluded_with=FieldE" json:"field_4"`
10182 Field5 string `validate:"excluded_with=Inner.FieldE" json:"field_5"`
10183 Field6 string `validate:"excluded_with=Inner2.FieldE" json:"field_6"`
10184 }{
10185 Inner: &Inner{FieldE: "populated"},
10186 Inner2: &Inner{FieldE: "populated"},
10187 FieldE: "populated",
10188 }
10189
10190 validate = New()
10191
10192 errs = validate.Struct(test3)
10193 Equal(t, errs, nil)
1020410194 }
1020510195
1020610196 func TestExcludedWithout(t *testing.T) {
1026510255 name := fmt.Sprintf("Field%d", i)
1026610256 AssertError(t, errs, name, name, name, name, "excluded_without")
1026710257 }
10258
10259 test3 := struct {
10260 Inner *Inner
10261 Inner2 *Inner
10262 Field string `validate:"omitempty" json:"field"`
10263 FieldE string `validate:"omitempty" json:"field_e"`
10264 Field1 string `validate:"excluded_without=Field" json:"field_1"`
10265 Field2 *string `validate:"excluded_without=Field" json:"field_2"`
10266 Field3 map[string]string `validate:"excluded_without=Field" json:"field_3"`
10267 Field4 interface{} `validate:"excluded_without=Field" json:"field_4"`
10268 Field5 string `validate:"excluded_without=Inner.Field" json:"field_5"`
10269 }{
10270 Inner: &Inner{Field: &fieldVal},
10271 Field: "populated",
10272 }
10273
10274 validate = New()
10275
10276 errs = validate.Struct(test3)
10277 Equal(t, errs, nil)
1026810278 }
1026910279
1027010280 func TestExcludedWithAll(t *testing.T) {
1033310343 name := fmt.Sprintf("Field%d", i)
1033410344 AssertError(t, errs, name, name, name, name, "excluded_with_all")
1033510345 }
10346
10347 test3 := struct {
10348 Inner *Inner
10349 Inner2 *Inner
10350 Field string `validate:"omitempty" json:"field"`
10351 FieldE string `validate:"omitempty" json:"field_e"`
10352 Field1 string `validate:"excluded_with_all=FieldE Field" json:"field_1"`
10353 Field2 *string `validate:"excluded_with_all=FieldE Field" json:"field_2"`
10354 Field3 map[string]string `validate:"excluded_with_all=FieldE Field" json:"field_3"`
10355 Field4 interface{} `validate:"excluded_with_all=FieldE Field" json:"field_4"`
10356 Field5 string `validate:"excluded_with_all=Inner.FieldE" json:"field_5"`
10357 Field6 string `validate:"excluded_with_all=Inner2.FieldE" json:"field_6"`
10358 }{
10359 Inner: &Inner{FieldE: "populated"},
10360 Inner2: &Inner{FieldE: "populated"},
10361 Field: "populated",
10362 FieldE: "populated",
10363 }
10364
10365 validate = New()
10366
10367 errs = validate.Struct(test3)
10368 Equal(t, errs, nil)
1033610369 }
1033710370
1033810371 func TestExcludedWithoutAll(t *testing.T) {
1035110384 Field2 *string `validate:"excluded_without_all=Field FieldE" json:"field_2"`
1035210385 Field3 map[string]string `validate:"excluded_without_all=Field FieldE" json:"field_3"`
1035310386 Field4 interface{} `validate:"excluded_without_all=Field FieldE" json:"field_4"`
10354 Field5 string `validate:"excluded_without_all=Inner.Field Inner.Field2" json:"field_5"`
10387 Field5 string `validate:"excluded_without_all=Inner.Field Inner2.Field" json:"field_5"`
1035510388 }{
1035610389 Inner: &Inner{Field: &fieldVal},
10390 Inner2: &Inner{Field: &fieldVal},
1035710391 Field: "populated",
1035810392 Field1: fieldVal,
1035910393 Field2: &fieldVal,
1039710431 name := fmt.Sprintf("Field%d", i)
1039810432 AssertError(t, errs, name, name, name, name, "excluded_without_all")
1039910433 }
10434
10435 test3 := struct {
10436 Inner *Inner
10437 Inner2 *Inner
10438 Field string `validate:"omitempty" json:"field"`
10439 FieldE string `validate:"omitempty" json:"field_e"`
10440 Field1 string `validate:"excluded_without_all=Field FieldE" json:"field_1"`
10441 Field2 *string `validate:"excluded_without_all=Field FieldE" json:"field_2"`
10442 Field3 map[string]string `validate:"excluded_without_all=Field FieldE" json:"field_3"`
10443 Field4 interface{} `validate:"excluded_without_all=Field FieldE" json:"field_4"`
10444 Field5 string `validate:"excluded_without_all=Inner.Field Inner2.Field" json:"field_5"`
10445 }{
10446 Inner: &Inner{Field: &fieldVal},
10447 Inner2: &Inner{Field: &fieldVal},
10448 Field: "populated",
10449 FieldE: "populated",
10450 }
10451
10452 validate = New()
10453
10454 errs = validate.Struct(test3)
10455 Equal(t, errs, nil)
1040010456 }
1040110457
1040210458 func TestRequiredWithAll(t *testing.T) {
1045410510 }
1045510511
1045610512 func TestRequiredWithout(t *testing.T) {
10457
1045810513 type Inner struct {
1045910514 Field *string
1046010515 }
1052010575 }
1052110576
1052210577 func TestRequiredWithoutAll(t *testing.T) {
10523
1052410578 fieldVal := "test"
1052510579 test := struct {
1052610580 Field1 string `validate:"omitempty" json:"field_1"`
1057710631 }
1057810632
1057910633 func TestAbilityToValidateNils(t *testing.T) {
10580
1058110634 type TestStruct struct {
1058210635 Test *string `validate:"nil"`
1058310636 }
1071910772 }
1072010773
1072110774 func Test_hostnameport_validator(t *testing.T) {
10722
1072310775 type Host struct {
1072410776 Addr string `validate:"hostname_port"`
1072510777 }
1082110873 PanicMatches(t, func() {
1082210874 _ = validate.Var(2, "uppercase")
1082310875 }, "Bad field type int")
10824
1082510876 }
1082610877
1082710878 func TestDatetimeValidation(t *testing.T) {
1103211083 })
1103311084 }
1103411085 }
11086
11087 func TestBCP47LanguageTagValidation(t *testing.T) {
11088 tests := []struct {
11089 value string `validate:"bcp47_language_tag"`
11090 tag string
11091 expected bool
11092 }{
11093 {"en-US", "bcp47_language_tag", true},
11094 {"en_GB", "bcp47_language_tag", true},
11095 {"es", "bcp47_language_tag", true},
11096 {"English", "bcp47_language_tag", false},
11097 {"ESES", "bcp47_language_tag", false},
11098 {"az-Cyrl-AZ", "bcp47_language_tag", true},
11099 {"en-029", "bcp47_language_tag", true},
11100 {"xog", "bcp47_language_tag", true},
11101 }
11102
11103 validate := New()
11104
11105 for i, test := range tests {
11106
11107 errs := validate.Var(test.value, test.tag)
11108
11109 if test.expected {
11110 if !IsEqual(errs, nil) {
11111 t.Fatalf("Index: %d locale failed Error: %s", i, errs)
11112 }
11113 } else {
11114 if IsEqual(errs, nil) {
11115 t.Fatalf("Index: %d locale failed Error: %s", i, errs)
11116 } else {
11117 val := getError(errs, "", "")
11118 if val.Tag() != "bcp47_language_tag" {
11119 t.Fatalf("Index: %d locale failed Error: %s", i, errs)
11120 }
11121 }
11122 }
11123 }
11124
11125 PanicMatches(t, func() {
11126 _ = validate.Var(2, "bcp47_language_tag")
11127 }, "Bad field type int")
11128 }
11129
11130 func TestBicIsoFormatValidation(t *testing.T) {
11131 tests := []struct {
11132 value string `validate:"bic"`
11133 tag string
11134 expected bool
11135 }{
11136 {"SBICKEN1345", "bic", true},
11137 {"SBICKEN1", "bic", true},
11138 {"SBICKENY", "bic", true},
11139 {"SBICKEN1YYP", "bic", true},
11140 {"SBIC23NXXX", "bic", false},
11141 {"S23CKENXXXX", "bic", false},
11142 {"SBICKENXX", "bic", false},
11143 {"SBICKENXX9", "bic", false},
11144 {"SBICKEN13458", "bic", false},
11145 {"SBICKEN", "bic", false},
11146 }
11147
11148 validate := New()
11149
11150 for i, test := range tests {
11151
11152 errs := validate.Var(test.value, test.tag)
11153
11154 if test.expected {
11155 if !IsEqual(errs, nil) {
11156 t.Fatalf("Index: %d bic failed Error: %s", i, errs)
11157 }
11158 } else {
11159 if IsEqual(errs, nil) {
11160 t.Fatalf("Index: %d bic failed Error: %s", i, errs)
11161 } else {
11162 val := getError(errs, "", "")
11163 if val.Tag() != "bic" {
11164 t.Fatalf("Index: %d bic failed Error: %s", i, errs)
11165 }
11166 }
11167 }
11168 }
11169 }
11170
11171 func TestPostCodeByIso3166Alpha2(t *testing.T) {
11172 tests := map[string][]struct {
11173 value string
11174 expected bool
11175 }{
11176 "VN": {
11177 {"ABC", false},
11178 {"700000", true},
11179 {"A1", false},
11180 },
11181 "GB": {
11182 {"EC1A 1BB", true},
11183 {"CF10 1B1H", false},
11184 },
11185 "VI": {
11186 {"00803", true},
11187 {"1234567", false},
11188 },
11189 "LC": { // not support regexp for post code
11190 {"123456", false},
11191 },
11192 "XX": { // not support country
11193 {"123456", false},
11194 },
11195 }
11196
11197 validate := New()
11198
11199 for cc, ccTests := range tests {
11200 for i, test := range ccTests {
11201 errs := validate.Var(test.value, fmt.Sprintf("postcode_iso3166_alpha2=%s", cc))
11202
11203 if test.expected {
11204 if !IsEqual(errs, nil) {
11205 t.Fatalf("Index: %d postcode_iso3166_alpha2=%s failed Error: %s", i, cc, errs)
11206 }
11207 } else {
11208 if IsEqual(errs, nil) {
11209 t.Fatalf("Index: %d postcode_iso3166_alpha2=%s failed Error: %s", i, cc, errs)
11210 }
11211 }
11212 }
11213 }
11214 }
11215
11216 func TestPostCodeByIso3166Alpha2Field(t *testing.T) {
11217 tests := []struct {
11218 Value string `validate:"postcode_iso3166_alpha2_field=CountryCode"`
11219 CountryCode interface{}
11220 expected bool
11221 }{
11222 {"ABC", "VN", false},
11223 {"700000", "VN", true},
11224 {"A1", "VN", false},
11225 {"EC1A 1BB", "GB", true},
11226 {"CF10 1B1H", "GB", false},
11227 {"00803", "VI", true},
11228 {"1234567", "VI", false},
11229 {"123456", "LC", false}, // not support regexp for post code
11230 {"123456", "XX", false}, // not support country
11231 }
11232
11233 validate := New()
11234
11235 for i, test := range tests {
11236 errs := validate.Struct(test)
11237 if test.expected {
11238 if !IsEqual(errs, nil) {
11239 t.Fatalf("Index: %d postcode_iso3166_alpha2_field=CountryCode failed Error: %s", i, errs)
11240 }
11241 } else {
11242 if IsEqual(errs, nil) {
11243 t.Fatalf("Index: %d postcode_iso3166_alpha2_field=CountryCode failed Error: %s", i, errs)
11244 }
11245 }
11246 }
11247 }
11248
11249 func TestPostCodeByIso3166Alpha2Field_WrongField(t *testing.T) {
11250 type test struct {
11251 Value string `validate:"postcode_iso3166_alpha2_field=CountryCode"`
11252 CountryCode1 interface{}
11253 expected bool
11254 }
11255
11256 errs := New().Struct(test{"ABC", "VN", false})
11257 assert.NotEqual(t, nil, errs)
11258 }
11259
11260 func TestPostCodeByIso3166Alpha2Field_MissingParam(t *testing.T) {
11261 type test struct {
11262 Value string `validate:"postcode_iso3166_alpha2_field="`
11263 CountryCode1 interface{}
11264 expected bool
11265 }
11266
11267 errs := New().Struct(test{"ABC", "VN", false})
11268 assert.NotEqual(t, nil, errs)
11269 }
11270
11271 func TestPostCodeByIso3166Alpha2Field_InvalidKind(t *testing.T) {
11272 type test struct {
11273 Value string `validate:"postcode_iso3166_alpha2_field=CountryCode"`
11274 CountryCode interface{}
11275 expected bool
11276 }
11277 defer func() { _ = recover() }()
11278
11279 _ = New().Struct(test{"ABC", 123, false})
11280 t.Errorf("Didn't panic as expected")
11281 }