@@ -78,6 +78,7 @@ func (s *tagCacheMap) Set(key string, value *cachedTag) {
7878// Validate contains the validator settings passed in using the Config struct
7979type Validate struct {
8080 tagName string
81+ fieldNameTag string
8182 validationFuncs map [string ]Func
8283 customTypeFuncs map [reflect.Type ]CustomTypeFunc
8384 aliasValidators map [string ]string
@@ -96,7 +97,8 @@ func (v *Validate) initCheck() {
9697// Config contains the options that a Validator instance will use.
9798// It is passed to the New() function
9899type Config struct {
99- TagName string
100+ TagName string
101+ FieldNameTag string
100102}
101103
102104// CustomTypeFunc allows for overriding or adding custom field type handler functions
@@ -137,6 +139,7 @@ func (ve ValidationErrors) Error() string {
137139// with other properties that may be needed for error message creation
138140type FieldError struct {
139141 Field string
142+ Name string
140143 Tag string
141144 ActualTag string
142145 Kind reflect.Kind
@@ -149,8 +152,9 @@ type FieldError struct {
149152func New (config * Config ) * Validate {
150153
151154 v := & Validate {
152- tagName : config .TagName ,
153- tagsCache : & tagCacheMap {m : map [string ]* cachedTag {}},
155+ tagName : config .TagName ,
156+ fieldNameTag : config .FieldNameTag ,
157+ tagsCache : & tagCacheMap {m : map [string ]* cachedTag {}},
154158 errsPool : & sync.Pool {New : func () interface {} {
155159 return ValidationErrors {}
156160 }}}
@@ -245,7 +249,7 @@ func (v *Validate) Field(field interface{}, tag string) error {
245249 errs := v .errsPool .Get ().(ValidationErrors )
246250 fieldVal := reflect .ValueOf (field )
247251
248- v .traverseField (fieldVal , fieldVal , fieldVal , blank , errs , false , tag , blank , false , false , nil )
252+ v .traverseField (fieldVal , fieldVal , fieldVal , blank , errs , false , tag , blank , blank , false , false , nil )
249253
250254 if len (errs ) == 0 {
251255 v .errsPool .Put (errs )
@@ -265,7 +269,7 @@ func (v *Validate) FieldWithValue(val interface{}, field interface{}, tag string
265269 errs := v .errsPool .Get ().(ValidationErrors )
266270 topVal := reflect .ValueOf (val )
267271
268- v .traverseField (topVal , topVal , reflect .ValueOf (field ), blank , errs , false , tag , blank , false , false , nil )
272+ v .traverseField (topVal , topVal , reflect .ValueOf (field ), blank , errs , false , tag , blank , blank , false , false , nil )
269273
270274 if len (errs ) == 0 {
271275 v .errsPool .Put (errs )
@@ -400,6 +404,7 @@ func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflec
400404 numFields := current .NumField ()
401405
402406 var fld reflect.StructField
407+ var customName string
403408
404409 for i := 0 ; i < numFields ; i ++ {
405410 fld = typ .Field (i )
@@ -417,12 +422,23 @@ func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflec
417422 }
418423 }
419424
420- v .traverseField (topStruct , currentStruct , current .Field (i ), errPrefix , errs , true , fld .Tag .Get (v .tagName ), fld .Name , partial , exclude , includeExclude )
425+ customName = fld .Name
426+ if v .fieldNameTag != "" {
427+
428+ name := strings .SplitN (fld .Tag .Get (v .fieldNameTag ), "," , 2 )[0 ]
429+
430+ // dash check is for json "-" means don't output in json
431+ if name != "" && name != "-" {
432+ customName = name
433+ }
434+ }
435+
436+ v .traverseField (topStruct , currentStruct , current .Field (i ), errPrefix , errs , true , fld .Tag .Get (v .tagName ), fld .Name , customName , partial , exclude , includeExclude )
421437 }
422438}
423439
424440// traverseField validates any field, be it a struct or single field, ensures it's validity and passes it along to be validated via it's tag options
425- func (v * Validate ) traverseField (topStruct reflect.Value , currentStruct reflect.Value , current reflect.Value , errPrefix string , errs ValidationErrors , isStructField bool , tag string , name string , partial bool , exclude bool , includeExclude map [string ]* struct {}) {
441+ func (v * Validate ) traverseField (topStruct reflect.Value , currentStruct reflect.Value , current reflect.Value , errPrefix string , errs ValidationErrors , isStructField bool , tag , name , customName string , partial bool , exclude bool , includeExclude map [string ]* struct {}) {
426442
427443 if tag == skipValidationTag {
428444 return
@@ -448,6 +464,7 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
448464
449465 if kind == reflect .Invalid {
450466 errs [errPrefix + name ] = & FieldError {
467+ Name : customName ,
451468 Field : name ,
452469 Tag : cTag .tags [0 ].tag ,
453470 ActualTag : cTag .tags [0 ].tagVals [0 ][0 ],
@@ -458,6 +475,7 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
458475 }
459476
460477 errs [errPrefix + name ] = & FieldError {
478+ Name : customName ,
461479 Field : name ,
462480 Tag : cTag .tags [0 ].tag ,
463481 ActualTag : cTag .tags [0 ].tagVals [0 ][0 ],
@@ -520,7 +538,7 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
520538 continue
521539 }
522540
523- if v .validateField (topStruct , currentStruct , current , typ , kind , errPrefix , errs , valTag , name ) {
541+ if v .validateField (topStruct , currentStruct , current , typ , kind , errPrefix , errs , valTag , name , customName ) {
524542 return
525543 }
526544 }
@@ -530,9 +548,9 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
530548 // or panic ;)
531549 switch kind {
532550 case reflect .Slice , reflect .Array :
533- v .traverseSlice (topStruct , currentStruct , current , errPrefix , errs , diveSubTag , name , partial , exclude , includeExclude )
551+ v .traverseSlice (topStruct , currentStruct , current , errPrefix , errs , diveSubTag , name , customName , partial , exclude , includeExclude )
534552 case reflect .Map :
535- v .traverseMap (topStruct , currentStruct , current , errPrefix , errs , diveSubTag , name , partial , exclude , includeExclude )
553+ v .traverseMap (topStruct , currentStruct , current , errPrefix , errs , diveSubTag , name , customName , partial , exclude , includeExclude )
536554 default :
537555 // throw error, if not a slice or map then should not have gotten here
538556 // bad dive tag
@@ -542,23 +560,23 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
542560}
543561
544562// traverseSlice traverses a Slice or Array's elements and passes them to traverseField for validation
545- func (v * Validate ) traverseSlice (topStruct reflect.Value , currentStruct reflect.Value , current reflect.Value , errPrefix string , errs ValidationErrors , tag string , name string , partial bool , exclude bool , includeExclude map [string ]* struct {}) {
563+ func (v * Validate ) traverseSlice (topStruct reflect.Value , currentStruct reflect.Value , current reflect.Value , errPrefix string , errs ValidationErrors , tag , name , customName string , partial bool , exclude bool , includeExclude map [string ]* struct {}) {
546564
547565 for i := 0 ; i < current .Len (); i ++ {
548- v .traverseField (topStruct , currentStruct , current .Index (i ), errPrefix , errs , false , tag , fmt .Sprintf (arrayIndexFieldName , name , i ), partial , exclude , includeExclude )
566+ v .traverseField (topStruct , currentStruct , current .Index (i ), errPrefix , errs , false , tag , fmt .Sprintf (arrayIndexFieldName , name , i ), fmt . Sprintf ( arrayIndexFieldName , customName , i ), partial , exclude , includeExclude )
549567 }
550568}
551569
552570// traverseMap traverses a map's elements and passes them to traverseField for validation
553- func (v * Validate ) traverseMap (topStruct reflect.Value , currentStruct reflect.Value , current reflect.Value , errPrefix string , errs ValidationErrors , tag string , name string , partial bool , exclude bool , includeExclude map [string ]* struct {}) {
571+ func (v * Validate ) traverseMap (topStruct reflect.Value , currentStruct reflect.Value , current reflect.Value , errPrefix string , errs ValidationErrors , tag , name , customName string , partial bool , exclude bool , includeExclude map [string ]* struct {}) {
554572
555573 for _ , key := range current .MapKeys () {
556- v .traverseField (topStruct , currentStruct , current .MapIndex (key ), errPrefix , errs , false , tag , fmt .Sprintf (mapIndexFieldName , name , key .Interface ()), partial , exclude , includeExclude )
574+ v .traverseField (topStruct , currentStruct , current .MapIndex (key ), errPrefix , errs , false , tag , fmt .Sprintf (mapIndexFieldName , name , key .Interface ()), fmt . Sprintf ( mapIndexFieldName , customName , key . Interface ()), partial , exclude , includeExclude )
557575 }
558576}
559577
560578// validateField validates a field based on the provided tag's key and param values and returns true if there is an error or false if all ok
561- func (v * Validate ) validateField (topStruct reflect.Value , currentStruct reflect.Value , current reflect.Value , currentType reflect.Type , currentKind reflect.Kind , errPrefix string , errs ValidationErrors , valTag * tagVals , name string ) bool {
579+ func (v * Validate ) validateField (topStruct reflect.Value , currentStruct reflect.Value , current reflect.Value , currentType reflect.Type , currentKind reflect.Kind , errPrefix string , errs ValidationErrors , valTag * tagVals , name , customName string ) bool {
562580
563581 var valFunc Func
564582 var ok bool
@@ -583,6 +601,7 @@ func (v *Validate) validateField(topStruct reflect.Value, currentStruct reflect.
583601
584602 if valTag .isAlias {
585603 errs [errPrefix + name ] = & FieldError {
604+ Name : customName ,
586605 Field : name ,
587606 Tag : valTag .tag ,
588607 ActualTag : errTag [1 :],
@@ -592,6 +611,7 @@ func (v *Validate) validateField(topStruct reflect.Value, currentStruct reflect.
592611 }
593612 } else {
594613 errs [errPrefix + name ] = & FieldError {
614+ Name : customName ,
595615 Field : name ,
596616 Tag : errTag [1 :],
597617 ActualTag : errTag [1 :],
@@ -614,6 +634,7 @@ func (v *Validate) validateField(topStruct reflect.Value, currentStruct reflect.
614634 }
615635
616636 errs [errPrefix + name ] = & FieldError {
637+ Name : customName ,
617638 Field : name ,
618639 Tag : valTag .tag ,
619640 ActualTag : valTag .tagVals [0 ][0 ],
0 commit comments