@ -62,105 +62,109 @@ var (
// you can add, remove or even replace items to suite your needs,
// you can add, remove or even replace items to suite your needs,
// or even disregard and use your own map if so desired.
// or even disregard and use your own map if so desired.
bakedInValidators = map [ string ] Func {
bakedInValidators = map [ string ] Func {
"required" : hasValue ,
"required" : hasValue ,
"isdefault" : isDefault ,
"required_with" : requiredWith ,
"len" : hasLengthOf ,
"required_with_all" : requiredWithAll ,
"min" : hasMinOf ,
"required_without" : requiredWithout ,
"max" : hasMaxOf ,
"required_without_all" : requiredWithoutAll ,
"eq" : isEq ,
"isdefault" : isDefault ,
"ne" : isNe ,
"len" : hasLengthOf ,
"lt" : isLt ,
"min" : hasMinOf ,
"lte" : isLte ,
"max" : hasMaxOf ,
"gt" : isGt ,
"eq" : isEq ,
"gte" : isGte ,
"ne" : isNe ,
"eqfield" : isEqField ,
"lt" : isLt ,
"eqcsfield" : isEqCrossStructField ,
"lte" : isLte ,
"necsfield" : isNeCrossStructField ,
"gt" : isGt ,
"gtcsfield" : isGtCrossStructField ,
"gte" : isGte ,
"gtecsfield" : isGteCrossStructField ,
"eqfield" : isEqField ,
"ltcsfield" : isLtCrossStructField ,
"eqcsfield" : isEqCrossStructField ,
"ltecsfield" : isLteCrossStructField ,
"necsfield" : isNeCrossStructField ,
"nefield" : isNeField ,
"gtcsfield" : isGtCrossStructField ,
"gtefield" : isGteField ,
"gtecsfield" : isGteCrossStructField ,
"gtfield" : isGtField ,
"ltcsfield" : isLtCrossStructField ,
"ltefield" : isLteField ,
"ltecsfield" : isLteCrossStructField ,
"ltfield" : isLtField ,
"nefield" : isNeField ,
"fieldcontains" : fieldContains ,
"gtefield" : isGteField ,
"fieldexcludes" : fieldExcludes ,
"gtfield" : isGtField ,
"alpha" : isAlpha ,
"ltefield" : isLteField ,
"alphanum" : isAlphanum ,
"ltfield" : isLtField ,
"alphaunicode" : isAlphaUnicode ,
"fieldcontains" : fieldContains ,
"alphanumunicode" : isAlphanumUnicode ,
"fieldexcludes" : fieldExcludes ,
"numeric" : isNumeric ,
"alpha" : isAlpha ,
"number" : isNumber ,
"alphanum" : isAlphanum ,
"hexadecimal" : isHexadecimal ,
"alphaunicode" : isAlphaUnicode ,
"hexcolor" : isHEXColor ,
"alphanumunicode" : isAlphanumUnicode ,
"rgb" : isRGB ,
"numeric" : isNumeric ,
"rgba" : isRGBA ,
"number" : isNumber ,
"hsl" : isHSL ,
"hexadecimal" : isHexadecimal ,
"hsla" : isHSLA ,
"hexcolor" : isHEXColor ,
"email" : isEmail ,
"rgb" : isRGB ,
"url" : isURL ,
"rgba" : isRGBA ,
"uri" : isURI ,
"hsl" : isHSL ,
"urn_rfc2141" : isUrnRFC2141 , // RFC 2141
"hsla" : isHSLA ,
"file" : isFile ,
"email" : isEmail ,
"base64" : isBase64 ,
"url" : isURL ,
"base64url" : isBase64URL ,
"uri" : isURI ,
"contains" : contains ,
"urn_rfc2141" : isUrnRFC2141 , // RFC 2141
"containsany" : containsAny ,
"file" : isFile ,
"containsrune" : containsRune ,
"base64" : isBase64 ,
"excludes" : excludes ,
"base64url" : isBase64URL ,
"excludesall" : excludesAll ,
"contains" : contains ,
"excludesrune" : excludesRune ,
"containsany" : containsAny ,
"startswith" : startsWith ,
"containsrune" : containsRune ,
"endswith" : endsWith ,
"excludes" : excludes ,
"isbn" : isISBN ,
"excludesall" : excludesAll ,
"isbn10" : isISBN10 ,
"excludesrune" : excludesRune ,
"isbn13" : isISBN13 ,
"startswith" : startsWith ,
"eth_addr" : isEthereumAddress ,
"endswith" : endsWith ,
"btc_addr" : isBitcoinAddress ,
"isbn" : isISBN ,
"btc_addr_bech32" : isBitcoinBech32Address ,
"isbn10" : isISBN10 ,
"uuid" : isUUID ,
"isbn13" : isISBN13 ,
"uuid3" : isUUID3 ,
"eth_addr" : isEthereumAddress ,
"uuid4" : isUUID4 ,
"btc_addr" : isBitcoinAddress ,
"uuid5" : isUUID5 ,
"btc_addr_bech32" : isBitcoinBech32Address ,
"uuid_rfc4122" : isUUIDRFC4122 ,
"uuid" : isUUID ,
"uuid3_rfc4122" : isUUID3RFC4122 ,
"uuid3" : isUUID3 ,
"uuid4_rfc4122" : isUUID4RFC4122 ,
"uuid4" : isUUID4 ,
"uuid5_rfc4122" : isUUID5RFC4122 ,
"uuid5" : isUUID5 ,
"ascii" : isASCII ,
"uuid_rfc4122" : isUUIDRFC4122 ,
"printascii" : isPrintableASCII ,
"uuid3_rfc4122" : isUUID3RFC4122 ,
"multibyte" : hasMultiByteCharacter ,
"uuid4_rfc4122" : isUUID4RFC4122 ,
"datauri" : isDataURI ,
"uuid5_rfc4122" : isUUID5RFC4122 ,
"latitude" : isLatitude ,
"ascii" : isASCII ,
"longitude" : isLongitude ,
"printascii" : isPrintableASCII ,
"ssn" : isSSN ,
"multibyte" : hasMultiByteCharacter ,
"ipv4" : isIPv4 ,
"datauri" : isDataURI ,
"ipv6" : isIPv6 ,
"latitude" : isLatitude ,
"ip" : isIP ,
"longitude" : isLongitude ,
"cidrv4" : isCIDRv4 ,
"ssn" : isSSN ,
"cidrv6" : isCIDRv6 ,
"ipv4" : isIPv4 ,
"cidr" : isCIDR ,
"ipv6" : isIPv6 ,
"tcp4_addr" : isTCP4AddrResolvable ,
"ip" : isIP ,
"tcp6_addr" : isTCP6AddrResolvable ,
"cidrv4" : isCIDRv4 ,
"tcp_addr" : isTCPAddrResolvable ,
"cidrv6" : isCIDRv6 ,
"udp4_addr" : isUDP4AddrResolvable ,
"cidr" : isCIDR ,
"udp6_addr" : isUDP6AddrResolvable ,
"tcp4_addr" : isTCP4AddrResolvable ,
"udp_addr" : isUDPAddrResolvable ,
"tcp6_addr" : isTCP6AddrResolvable ,
"ip4_addr" : isIP4AddrResolvable ,
"tcp_addr" : isTCPAddrResolvable ,
"ip6_addr" : isIP6AddrResolvable ,
"udp4_addr" : isUDP4AddrResolvable ,
"ip_addr" : isIPAddrResolvable ,
"udp6_addr" : isUDP6AddrResolvable ,
"unix_addr" : isUnixAddrResolvable ,
"udp_addr" : isUDPAddrResolvable ,
"mac" : isMAC ,
"ip4_addr" : isIP4AddrResolvable ,
"hostname" : isHostnameRFC952 , // RFC 952
"ip6_addr" : isIP6AddrResolvable ,
"hostname_rfc1123" : isHostnameRFC1123 , // RFC 1123
"ip_addr" : isIPAddrResolvable ,
"fqdn" : isFQDN ,
"unix_addr" : isUnixAddrResolvable ,
"unique" : isUnique ,
"mac" : isMAC ,
"oneof" : isOneOf ,
"hostname" : isHostnameRFC952 , // RFC 952
"html" : isHTML ,
"hostname_rfc1123" : isHostnameRFC1123 , // RFC 1123
"html_encoded" : isHTMLEncoded ,
"fqdn" : isFQDN ,
"url_encoded" : isURLEncoded ,
"unique" : isUnique ,
"dir" : isDir ,
"oneof" : isOneOf ,
"html" : isHTML ,
"html_encoded" : isHTMLEncoded ,
"url_encoded" : isURLEncoded ,
"dir" : isDir ,
}
}
)
)
@ -1297,22 +1301,101 @@ func isDefault(fl FieldLevel) bool {
// HasValue is the validation function for validating if the current field's value is not the default static value.
// HasValue is the validation function for validating if the current field's value is not the default static value.
func hasValue ( fl FieldLevel ) bool {
func hasValue ( fl FieldLevel ) bool {
return requireCheckFieldKind ( fl , "" )
}
// requireCheckField is a func for check field kind
func requireCheckFieldKind ( fl FieldLevel , param string ) bool {
field := fl . Field ( )
field := fl . Field ( )
if len ( param ) > 0 {
field = fl . Parent ( ) . FieldByName ( param )
}
switch field . Kind ( ) {
switch field . Kind ( ) {
case reflect . Slice , reflect . Map , reflect . Ptr , reflect . Interface , reflect . Chan , reflect . Func :
case reflect . Slice , reflect . Map , reflect . Ptr , reflect . Interface , reflect . Chan , reflect . Func :
return ! field . IsNil ( )
return ! field . IsNil ( )
default :
default :
if fl . ( * validate ) . fldIsPointer && field . Interface ( ) != nil {
if fl . ( * validate ) . fldIsPointer && field . Interface ( ) != nil {
return true
return true
}
}
return field . IsValid ( ) && field . Interface ( ) != reflect . Zero ( field . Type ( ) ) . Interface ( )
return field . IsValid ( ) && field . Interface ( ) != reflect . Zero ( field . Type ( ) ) . Interface ( )
}
}
}
}
// RequiredWith is the validation function
// The field under validation must be present and not empty only if any of the other specified fields are present.
func requiredWith ( fl FieldLevel ) bool {
params := parseOneOfParam2 ( fl . Param ( ) )
for _ , param := range params {
if requireCheckFieldKind ( fl , param ) {
return requireCheckFieldKind ( fl , "" )
}
}
return true
}
// RequiredWithAll is the validation function
// The field under validation must be present and not empty only if all of the other specified fields are present.
func requiredWithAll ( fl FieldLevel ) bool {
isValidateCurrentField := true
params := parseOneOfParam2 ( fl . Param ( ) )
for _ , param := range params {
if ! requireCheckFieldKind ( fl , param ) {
isValidateCurrentField = false
}
}
if isValidateCurrentField {
return requireCheckFieldKind ( fl , "" )
}
return true
}
// RequiredWithout is the validation function
// The field under validation must be present and not empty only when any of the other specified fields are not present.
func requiredWithout ( fl FieldLevel ) bool {
isValidateCurrentField := false
params := parseOneOfParam2 ( fl . Param ( ) )
for _ , param := range params {
if requireCheckFieldKind ( fl , param ) {
isValidateCurrentField = true
}
}
if ! isValidateCurrentField {
return requireCheckFieldKind ( fl , "" )
}
return true
}
// RequiredWithoutAll is the validation function
// The field under validation must be present and not empty only when all of the other specified fields are not present.
func requiredWithoutAll ( fl FieldLevel ) bool {
isValidateCurrentField := true
params := parseOneOfParam2 ( fl . Param ( ) )
for _ , param := range params {
if requireCheckFieldKind ( fl , param ) {
isValidateCurrentField = false
}
}
if isValidateCurrentField {
return requireCheckFieldKind ( fl , "" )
}
return true
}
// IsGteField is the validation function for validating if the current field's value is greater than or equal to the field specified by the param's value.
// IsGteField is the validation function for validating if the current field's value is greater than or equal to the field specified by the param's value.
func isGteField ( fl FieldLevel ) bool {
func isGteField ( fl FieldLevel ) bool {