add extra param of current struct.
pull/23/head v4.0
Dean Karn 10 years ago
parent 37ced95e7a
commit a3cb430fa1
  1. 9
      README.md
  2. 198
      baked_in.go
  3. 8
      doc.go
  4. 36
      validator.go
  5. 6
      validator_test.go

@ -1,6 +1,7 @@
Package go-validate-yourself
================
[![Build Status](https://travis-ci.org/joeybloggs/go-validate-yourself.svg?branch=v4-development)](https://travis-ci.org/joeybloggs/go-validate-yourself)
[![Build Status](https://travis-ci.org/joeybloggs/go-validate-yourself.svg?branch=v4)](https://travis-ci.org/joeybloggs/go-validate-yourself)
[![GoDoc](https://godoc.org/gopkg.in/joeybloggs/go-validate-yourself.v4?status.svg)](https://godoc.org/gopkg.in/joeybloggs/go-validate-yourself.v4)
Package validator implements value validations for structs and individual fields based on tags.
@ -22,7 +23,7 @@ And then just import the package into your own code.
Usage
=====
Please see http://godoc.org/gopkg.in/joeybloggs/go-validate-yourself.v3 for detailed usage docs.
Please see http://godoc.org/gopkg.in/joeybloggs/go-validate-yourself.v4 for detailed usage docs.
Contributing
============
@ -36,3 +37,7 @@ however, there will also be a v2-development brach even though v2 doesn't exist
I strongly encourage everyone whom creates a custom validation function to contribute them and
help make this package even better.
License
=======
Distributed under MIT License, please see license file in code for more details.

@ -38,7 +38,7 @@ var BakedInValidators = map[string]ValidationFunc{
"uri": isURI,
}
func isURI(val interface{}, field interface{}, param string) bool {
func isURI(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -53,7 +53,7 @@ func isURI(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isURL(val interface{}, field interface{}, param string) bool {
func isURL(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -76,7 +76,7 @@ func isURL(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isEmail(val interface{}, field interface{}, param string) bool {
func isEmail(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -89,7 +89,7 @@ func isEmail(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isHsla(val interface{}, field interface{}, param string) bool {
func isHsla(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -102,7 +102,7 @@ func isHsla(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isHsl(val interface{}, field interface{}, param string) bool {
func isHsl(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -115,7 +115,7 @@ func isHsl(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isRgba(val interface{}, field interface{}, param string) bool {
func isRgba(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -128,7 +128,7 @@ func isRgba(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isRgb(val interface{}, field interface{}, param string) bool {
func isRgb(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -141,7 +141,7 @@ func isRgb(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isHexcolor(val interface{}, field interface{}, param string) bool {
func isHexcolor(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -154,7 +154,7 @@ func isHexcolor(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isHexadecimal(val interface{}, field interface{}, param string) bool {
func isHexadecimal(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -167,7 +167,7 @@ func isHexadecimal(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isNumber(val interface{}, field interface{}, param string) bool {
func isNumber(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -180,7 +180,7 @@ func isNumber(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isNumeric(val interface{}, field interface{}, param string) bool {
func isNumeric(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -193,7 +193,7 @@ func isNumeric(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isAlphanum(val interface{}, field interface{}, param string) bool {
func isAlphanum(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -206,7 +206,7 @@ func isAlphanum(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isAlpha(val interface{}, field interface{}, param string) bool {
func isAlpha(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -219,7 +219,7 @@ func isAlpha(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func hasValue(val interface{}, field interface{}, param string) bool {
func hasValue(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -233,45 +233,45 @@ func hasValue(val interface{}, field interface{}, param string) bool {
}
}
func isGteField(val interface{}, field interface{}, param string) bool {
func isGteField(top interface{}, current interface{}, field interface{}, param string) bool {
if val == nil {
if current == nil {
panic("struct not passed for cross validation")
}
topVal := reflect.ValueOf(val)
currentVal := reflect.ValueOf(current)
if topVal.Kind() == reflect.Ptr && !topVal.IsNil() {
topVal = reflect.ValueOf(topVal.Elem().Interface())
if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
currentVal = reflect.ValueOf(currentVal.Elem().Interface())
}
var topFieldVal reflect.Value
var currentFielVal reflect.Value
switch topVal.Kind() {
switch currentVal.Kind() {
case reflect.Struct:
if topVal.Type() == reflect.TypeOf(time.Time{}) {
topFieldVal = topVal
if currentVal.Type() == reflect.TypeOf(time.Time{}) {
currentFielVal = currentVal
break
}
f := topVal.FieldByName(param)
f := currentVal.FieldByName(param)
if f.Kind() == reflect.Invalid {
panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
}
topFieldVal = f
currentFielVal = f
default:
topFieldVal = topVal
currentFielVal = currentVal
}
if topFieldVal.Kind() == reflect.Ptr && !topFieldVal.IsNil() {
if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
topFieldVal = reflect.ValueOf(topFieldVal.Elem().Interface())
currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
}
fv := reflect.ValueOf(field)
@ -280,25 +280,25 @@ func isGteField(val interface{}, field interface{}, param string) bool {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return fv.Int() >= topFieldVal.Int()
return fv.Int() >= currentFielVal.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return fv.Uint() >= topFieldVal.Uint()
return fv.Uint() >= currentFielVal.Uint()
case reflect.Float32, reflect.Float64:
return fv.Float() >= topFieldVal.Float()
return fv.Float() >= currentFielVal.Float()
case reflect.Struct:
if fv.Type() == reflect.TypeOf(time.Time{}) {
if topFieldVal.Type() != reflect.TypeOf(time.Time{}) {
if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
panic("Bad Top Level field type")
}
t := topFieldVal.Interface().(time.Time)
t := currentFielVal.Interface().(time.Time)
fieldTime := field.(time.Time)
return fieldTime.After(t) || fieldTime.Equal(t)
@ -308,45 +308,45 @@ func isGteField(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isGtField(val interface{}, field interface{}, param string) bool {
func isGtField(top interface{}, current interface{}, field interface{}, param string) bool {
if val == nil {
if current == nil {
panic("struct not passed for cross validation")
}
topVal := reflect.ValueOf(val)
currentVal := reflect.ValueOf(current)
if topVal.Kind() == reflect.Ptr && !topVal.IsNil() {
topVal = reflect.ValueOf(topVal.Elem().Interface())
if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
currentVal = reflect.ValueOf(currentVal.Elem().Interface())
}
var topFieldVal reflect.Value
var currentFielVal reflect.Value
switch topVal.Kind() {
switch currentVal.Kind() {
case reflect.Struct:
if topVal.Type() == reflect.TypeOf(time.Time{}) {
topFieldVal = topVal
if currentVal.Type() == reflect.TypeOf(time.Time{}) {
currentFielVal = currentVal
break
}
f := topVal.FieldByName(param)
f := currentVal.FieldByName(param)
if f.Kind() == reflect.Invalid {
panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
}
topFieldVal = f
currentFielVal = f
default:
topFieldVal = topVal
currentFielVal = currentVal
}
if topFieldVal.Kind() == reflect.Ptr && !topFieldVal.IsNil() {
if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
topFieldVal = reflect.ValueOf(topFieldVal.Elem().Interface())
currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
}
fv := reflect.ValueOf(field)
@ -355,25 +355,25 @@ func isGtField(val interface{}, field interface{}, param string) bool {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return fv.Int() > topFieldVal.Int()
return fv.Int() > currentFielVal.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return fv.Uint() > topFieldVal.Uint()
return fv.Uint() > currentFielVal.Uint()
case reflect.Float32, reflect.Float64:
return fv.Float() > topFieldVal.Float()
return fv.Float() > currentFielVal.Float()
case reflect.Struct:
if fv.Type() == reflect.TypeOf(time.Time{}) {
if topFieldVal.Type() != reflect.TypeOf(time.Time{}) {
if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
panic("Bad Top Level field type")
}
t := topFieldVal.Interface().(time.Time)
t := currentFielVal.Interface().(time.Time)
fieldTime := field.(time.Time)
return fieldTime.After(t)
@ -383,7 +383,7 @@ func isGtField(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isGte(val interface{}, field interface{}, param string) bool {
func isGte(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -428,7 +428,7 @@ func isGte(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isGt(val interface{}, field interface{}, param string) bool {
func isGt(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -472,7 +472,7 @@ func isGt(val interface{}, field interface{}, param string) bool {
// length tests whether a variable's length is equal to a given
// value. For strings it tests the number of characters whereas
// for maps and slices it tests the number of items.
func hasLengthOf(val interface{}, field interface{}, param string) bool {
func hasLengthOf(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -511,50 +511,50 @@ func hasLengthOf(val interface{}, field interface{}, param string) bool {
// number. For number types, it's a simple lesser-than test; for
// strings it tests the number of characters whereas for maps
// and slices it tests the number of items.
func hasMinOf(val interface{}, field interface{}, param string) bool {
func hasMinOf(top interface{}, current interface{}, field interface{}, param string) bool {
return isGte(val, field, param)
return isGte(top, current, field, param)
}
func isLteField(val interface{}, field interface{}, param string) bool {
func isLteField(top interface{}, current interface{}, field interface{}, param string) bool {
if val == nil {
if current == nil {
panic("struct not passed for cross validation")
}
topVal := reflect.ValueOf(val)
currentVal := reflect.ValueOf(current)
if topVal.Kind() == reflect.Ptr && !topVal.IsNil() {
topVal = reflect.ValueOf(topVal.Elem().Interface())
if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
currentVal = reflect.ValueOf(currentVal.Elem().Interface())
}
var topFieldVal reflect.Value
var currentFielVal reflect.Value
switch topVal.Kind() {
switch currentVal.Kind() {
case reflect.Struct:
if topVal.Type() == reflect.TypeOf(time.Time{}) {
topFieldVal = topVal
if currentVal.Type() == reflect.TypeOf(time.Time{}) {
currentFielVal = currentVal
break
}
f := topVal.FieldByName(param)
f := currentVal.FieldByName(param)
if f.Kind() == reflect.Invalid {
panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
}
topFieldVal = f
currentFielVal = f
default:
topFieldVal = topVal
currentFielVal = currentVal
}
if topFieldVal.Kind() == reflect.Ptr && !topFieldVal.IsNil() {
if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
topFieldVal = reflect.ValueOf(topFieldVal.Elem().Interface())
currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
}
fv := reflect.ValueOf(field)
@ -563,25 +563,25 @@ func isLteField(val interface{}, field interface{}, param string) bool {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return fv.Int() <= topFieldVal.Int()
return fv.Int() <= currentFielVal.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return fv.Uint() <= topFieldVal.Uint()
return fv.Uint() <= currentFielVal.Uint()
case reflect.Float32, reflect.Float64:
return fv.Float() <= topFieldVal.Float()
return fv.Float() <= currentFielVal.Float()
case reflect.Struct:
if fv.Type() == reflect.TypeOf(time.Time{}) {
if topFieldVal.Type() != reflect.TypeOf(time.Time{}) {
if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
panic("Bad Top Level field type")
}
t := topFieldVal.Interface().(time.Time)
t := currentFielVal.Interface().(time.Time)
fieldTime := field.(time.Time)
return fieldTime.Before(t) || fieldTime.Equal(t)
@ -591,45 +591,45 @@ func isLteField(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isLtField(val interface{}, field interface{}, param string) bool {
func isLtField(top interface{}, current interface{}, field interface{}, param string) bool {
if val == nil {
if current == nil {
panic("struct not passed for cross validation")
}
topVal := reflect.ValueOf(val)
currentVal := reflect.ValueOf(current)
if topVal.Kind() == reflect.Ptr && !topVal.IsNil() {
topVal = reflect.ValueOf(topVal.Elem().Interface())
if currentVal.Kind() == reflect.Ptr && !currentVal.IsNil() {
currentVal = reflect.ValueOf(currentVal.Elem().Interface())
}
var topFieldVal reflect.Value
var currentFielVal reflect.Value
switch topVal.Kind() {
switch currentVal.Kind() {
case reflect.Struct:
if topVal.Type() == reflect.TypeOf(time.Time{}) {
topFieldVal = topVal
if currentVal.Type() == reflect.TypeOf(time.Time{}) {
currentFielVal = currentVal
break
}
f := topVal.FieldByName(param)
f := currentVal.FieldByName(param)
if f.Kind() == reflect.Invalid {
panic(fmt.Sprintf("Field \"%s\" not found in struct", param))
}
topFieldVal = f
currentFielVal = f
default:
topFieldVal = topVal
currentFielVal = currentVal
}
if topFieldVal.Kind() == reflect.Ptr && !topFieldVal.IsNil() {
if currentFielVal.Kind() == reflect.Ptr && !currentFielVal.IsNil() {
topFieldVal = reflect.ValueOf(topFieldVal.Elem().Interface())
currentFielVal = reflect.ValueOf(currentFielVal.Elem().Interface())
}
fv := reflect.ValueOf(field)
@ -638,25 +638,25 @@ func isLtField(val interface{}, field interface{}, param string) bool {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return fv.Int() < topFieldVal.Int()
return fv.Int() < currentFielVal.Int()
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return fv.Uint() < topFieldVal.Uint()
return fv.Uint() < currentFielVal.Uint()
case reflect.Float32, reflect.Float64:
return fv.Float() < topFieldVal.Float()
return fv.Float() < currentFielVal.Float()
case reflect.Struct:
if fv.Type() == reflect.TypeOf(time.Time{}) {
if topFieldVal.Type() != reflect.TypeOf(time.Time{}) {
if currentFielVal.Type() != reflect.TypeOf(time.Time{}) {
panic("Bad Top Level field type")
}
t := topFieldVal.Interface().(time.Time)
t := currentFielVal.Interface().(time.Time)
fieldTime := field.(time.Time)
return fieldTime.Before(t)
@ -666,7 +666,7 @@ func isLtField(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isLte(val interface{}, field interface{}, param string) bool {
func isLte(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -711,7 +711,7 @@ func isLte(val interface{}, field interface{}, param string) bool {
panic(fmt.Sprintf("Bad field type %T", field))
}
func isLt(val interface{}, field interface{}, param string) bool {
func isLt(top interface{}, current interface{}, field interface{}, param string) bool {
st := reflect.ValueOf(field)
@ -757,9 +757,9 @@ func isLt(val interface{}, field interface{}, param string) bool {
// value. For numbers, it's a simple lesser-than test; for
// strings it tests the number of characters whereas for maps
// and slices it tests the number of items.
func hasMaxOf(val interface{}, field interface{}, param string) bool {
func hasMaxOf(top interface{}, current interface{}, field interface{}, param string) bool {
return isLte(val, field, param)
return isLte(top, current, field, param)
}
// asInt retuns the parameter as a int64

@ -3,8 +3,6 @@ Package validator implements value validations for structs and individual fields
Built In Validator
v3 no longer contains a built in Validator instance.
myValidator = validator.New("validate", validator.BakedInFunctions)
errs := myValidator.ValidateStruct(//your struct)
@ -79,7 +77,7 @@ Custom Functions
Custom functions can be added
//Structure
func customFunc(val interface{}, field interface{}, param string) bool {
func customFunc(top interface{}, current interface{}, field interface{}, param string) bool {
if whatever {
return false
@ -138,6 +136,10 @@ Bad Validator definitions are not handled by the library
Baked In Validators and Tags
NOTE: Baked In Cross field validation only compares fields on the same struct,
if cross field + cross struct validation is needed your own custom validator
should be implemented.
Here is a list of the current built in validators:
-

@ -101,8 +101,12 @@ func (e *StructValidationErrors) Flatten() map[string]*FieldValidationError {
return errs
}
// ValidationFunc that accepts a value(optional usage), a field and parameter(optional usage) for use in validation
type ValidationFunc func(val interface{}, v interface{}, param string) bool
// ValidationFunc accepts all values needed for file and cross field validation
// top = top level struct when validating by struct otherwise nil
// current = current level struct when validating by struct otherwise optional comparison value
// f = field value for validation
// param = parameter used in validation i.e. gt=0 param would be 0
type ValidationFunc func(top interface{}, current interface{}, f interface{}, param string) bool
// Validator implements the Validator Struct
// NOTE: Fields within are not thread safe and that is on purpose
@ -153,11 +157,11 @@ func (v *Validator) AddFunction(key string, f ValidationFunc) error {
// ValidateStruct validates a struct and returns a struct containing the errors
func (v *Validator) ValidateStruct(s interface{}) *StructValidationErrors {
return v.validateStructRecursive(s, s)
return v.validateStructRecursive(s, s, s)
}
// validateStructRecursive validates a struct recursivly and passes the top level struct around for use in validator functions and returns a struct containing the errors
func (v *Validator) validateStructRecursive(top interface{}, s interface{}) *StructValidationErrors {
func (v *Validator) validateStructRecursive(top interface{}, current interface{}, s interface{}) *StructValidationErrors {
structValue := reflect.ValueOf(s)
structType := reflect.TypeOf(s)
@ -170,7 +174,7 @@ func (v *Validator) validateStructRecursive(top interface{}, s interface{}) *Str
}
if structValue.Kind() == reflect.Ptr && !structValue.IsNil() {
return v.validateStructRecursive(top, structValue.Elem().Interface())
return v.validateStructRecursive(top, current, structValue.Elem().Interface())
}
if structValue.Kind() != reflect.Struct && structValue.Kind() != reflect.Interface {
@ -209,7 +213,7 @@ func (v *Validator) validateStructRecursive(top interface{}, s interface{}) *Str
if valueField.Type() == reflect.TypeOf(time.Time{}) {
if fieldError := v.validateFieldByNameAndTagAndValue(top, valueField.Interface(), typeField.Name, tag); fieldError != nil {
if fieldError := v.validateFieldByNameAndTagAndValue(top, current, valueField.Interface(), typeField.Name, tag); fieldError != nil {
validationErrors.Errors[fieldError.Field] = fieldError
// free up memory reference
fieldError = nil
@ -221,7 +225,7 @@ func (v *Validator) validateStructRecursive(top interface{}, s interface{}) *Str
continue
}
if structErrors := v.validateStructRecursive(top, valueField.Interface()); structErrors != nil {
if structErrors := v.validateStructRecursive(top, valueField.Interface(), valueField.Interface()); structErrors != nil {
validationErrors.StructErrors[typeField.Name] = structErrors
// free up memory map no longer needed
structErrors = nil
@ -230,7 +234,7 @@ func (v *Validator) validateStructRecursive(top interface{}, s interface{}) *Str
default:
if fieldError := v.validateFieldByNameAndTagAndValue(top, valueField.Interface(), typeField.Name, tag); fieldError != nil {
if fieldError := v.validateFieldByNameAndTagAndValue(top, current, valueField.Interface(), typeField.Name, tag); fieldError != nil {
validationErrors.Errors[fieldError.Field] = fieldError
// free up memory reference
fieldError = nil
@ -254,17 +258,17 @@ func (v *Validator) ValidateFieldByTag(f interface{}, tag string) *FieldValidati
// ValidateFieldByTagAndValue allows validation of a single field, still using tag style validation to check multiple errors
func (v *Validator) ValidateFieldByTagAndValue(val interface{}, f interface{}, tag string) *FieldValidationError {
return v.validateFieldByNameAndTagAndValue(val, f, "", tag)
return v.validateFieldByNameAndTagAndValue(nil, val, f, "", tag)
}
func (v *Validator) validateFieldByNameAndTagAndValue(val interface{}, f interface{}, name string, tag string) *FieldValidationError {
func (v *Validator) validateFieldByNameAndTagAndValue(val interface{}, current interface{}, f interface{}, name string, tag string) *FieldValidationError {
// This is a double check if coming from ValidateStruct but need to be here in case function is called directly
if tag == noValidationTag {
return nil
}
if strings.Contains(tag, omitempty) && !hasValue(val, f, "") {
if strings.Contains(tag, omitempty) && !hasValue(val, current, f, "") {
return nil
}
@ -272,7 +276,7 @@ func (v *Validator) validateFieldByNameAndTagAndValue(val interface{}, f interfa
fieldKind := valueField.Kind()
if fieldKind == reflect.Ptr && !valueField.IsNil() {
return v.validateFieldByNameAndTagAndValue(val, valueField.Elem().Interface(), name, tag)
return v.validateFieldByNameAndTagAndValue(val, current, valueField.Elem().Interface(), name, tag)
}
fieldType := valueField.Type()
@ -300,7 +304,7 @@ func (v *Validator) validateFieldByNameAndTagAndValue(val interface{}, f interfa
for _, val := range orVals {
valErr, err = v.validateFieldByNameAndSingleTag(val, f, name, val)
valErr, err = v.validateFieldByNameAndSingleTag(val, current, f, name, val)
if err == nil {
return nil
@ -318,7 +322,7 @@ func (v *Validator) validateFieldByNameAndTagAndValue(val interface{}, f interfa
return valErr
}
if valErr, err = v.validateFieldByNameAndSingleTag(val, f, name, valTag); err != nil {
if valErr, err = v.validateFieldByNameAndSingleTag(val, current, f, name, valTag); err != nil {
valErr.Kind = valueField.Kind()
valErr.Type = fieldType
@ -330,7 +334,7 @@ func (v *Validator) validateFieldByNameAndTagAndValue(val interface{}, f interfa
return nil
}
func (v *Validator) validateFieldByNameAndSingleTag(val interface{}, f interface{}, name string, valTag string) (*FieldValidationError, error) {
func (v *Validator) validateFieldByNameAndSingleTag(val interface{}, current interface{}, f interface{}, name string, valTag string) (*FieldValidationError, error) {
vals := strings.Split(valTag, tagKeySeparator)
key := strings.Trim(vals[0], " ")
@ -361,7 +365,7 @@ func (v *Validator) validateFieldByNameAndSingleTag(val interface{}, f interface
param = strings.Trim(vals[1], " ")
}
if err := valFunc(val, f, param); !err {
if err := valFunc(val, current, f, param); !err {
valErr.Param = param
return valErr, errors.New(key)
}

@ -127,14 +127,14 @@ func AssertMapFieldError(s map[string]*validator.FieldValidationError, field str
c.Assert(val.ErrorTag, Equals, expectedTag)
}
func newValidatorFunc(val interface{}, field interface{}, param string) bool {
func newValidatorFunc(val interface{}, current interface{}, field interface{}, param string) bool {
return true
}
func isEqualFunc(val interface{}, field interface{}, param string) bool {
func isEqualFunc(val interface{}, current interface{}, field interface{}, param string) bool {
return val.(string) == field.(string)
return current.(string) == field.(string)
}
func (ms *MySuite) TestStructOnlyValidation(c *C) {

Loading…
Cancel
Save