@@ -413,7 +413,7 @@ func (v *Validate) StructPartial(current interface{}, fields ...string) error {
413413
414414 errs := v .errsPool .Get ().(ValidationErrors )
415415
416- v .tranverseStruct (sv , sv , sv , blank , errs , true , len (m ) != 0 , false , m )
416+ v .tranverseStruct (sv , sv , sv , blank , errs , true , len (m ) != 0 , false , m , false )
417417
418418 if len (errs ) == 0 {
419419 v .errsPool .Put (errs )
@@ -440,7 +440,7 @@ func (v *Validate) StructExcept(current interface{}, fields ...string) error {
440440
441441 errs := v .errsPool .Get ().(ValidationErrors )
442442
443- v .tranverseStruct (sv , sv , sv , blank , errs , true , len (m ) != 0 , true , m )
443+ v .tranverseStruct (sv , sv , sv , blank , errs , true , len (m ) != 0 , true , m , false )
444444
445445 if len (errs ) == 0 {
446446 v .errsPool .Put (errs )
@@ -459,7 +459,7 @@ func (v *Validate) Struct(current interface{}) error {
459459 errs := v .errsPool .Get ().(ValidationErrors )
460460 sv := reflect .ValueOf (current )
461461
462- v .tranverseStruct (sv , sv , sv , blank , errs , true , false , false , nil )
462+ v .tranverseStruct (sv , sv , sv , blank , errs , true , false , false , nil , false )
463463
464464 if len (errs ) == 0 {
465465 v .errsPool .Put (errs )
@@ -470,7 +470,7 @@ func (v *Validate) Struct(current interface{}) error {
470470}
471471
472472// tranverseStruct traverses a structs fields and then passes them to be validated by traverseField
473- func (v * Validate ) tranverseStruct (topStruct reflect.Value , currentStruct reflect.Value , current reflect.Value , errPrefix string , errs ValidationErrors , useStructName bool , partial bool , exclude bool , includeExclude map [string ]* struct {}) {
473+ func (v * Validate ) tranverseStruct (topStruct reflect.Value , currentStruct reflect.Value , current reflect.Value , errPrefix string , errs ValidationErrors , useStructName bool , partial bool , exclude bool , includeExclude map [string ]* struct {}, isStructOnly bool ) {
474474
475475 if current .Kind () == reflect .Ptr && ! current .IsNil () {
476476 current = current .Elem ()
@@ -487,39 +487,44 @@ func (v *Validate) tranverseStruct(topStruct reflect.Value, currentStruct reflec
487487 errPrefix += typ .Name () + "."
488488 }
489489
490- numFields := current .NumField ()
490+ // structonly tag present don't tranverseFields
491+ // but must still check and run below struct level validation
492+ // if present
493+ if ! isStructOnly {
494+ numFields := current .NumField ()
491495
492- var fld reflect.StructField
493- var customName string
496+ var fld reflect.StructField
497+ var customName string
494498
495- for i := 0 ; i < numFields ; i ++ {
496- fld = typ .Field (i )
499+ for i := 0 ; i < numFields ; i ++ {
500+ fld = typ .Field (i )
497501
498- if ! unicode .IsUpper (rune (fld .Name [0 ])) {
499- continue
500- }
502+ if ! unicode .IsUpper (rune (fld .Name [0 ])) {
503+ continue
504+ }
501505
502- if partial {
506+ if partial {
503507
504- _ , ok = includeExclude [errPrefix + fld .Name ]
508+ _ , ok = includeExclude [errPrefix + fld .Name ]
505509
506- if (ok && exclude ) || (! ok && ! exclude ) {
507- continue
510+ if (ok && exclude ) || (! ok && ! exclude ) {
511+ continue
512+ }
508513 }
509- }
510514
511- customName = fld .Name
512- if v .fieldNameTag != "" {
515+ customName = fld .Name
516+ if v .fieldNameTag != "" {
513517
514- name := strings .SplitN (fld .Tag .Get (v .fieldNameTag ), "," , 2 )[0 ]
518+ name := strings .SplitN (fld .Tag .Get (v .fieldNameTag ), "," , 2 )[0 ]
515519
516- // dash check is for json "-" means don't output in json
517- if name != "" && name != "-" {
518- customName = name
520+ // dash check is for json "-" means don't output in json
521+ if name != "" && name != "-" {
522+ customName = name
523+ }
519524 }
520- }
521525
522- v .traverseField (topStruct , currentStruct , current .Field (i ), errPrefix , errs , true , fld .Tag .Get (v .tagName ), fld .Name , customName , partial , exclude , includeExclude )
526+ v .traverseField (topStruct , currentStruct , current .Field (i ), errPrefix , errs , true , fld .Tag .Get (v .tagName ), fld .Name , customName , partial , exclude , includeExclude )
527+ }
523528 }
524529
525530 // check if any struct level validations, after all field validations already checked.
@@ -590,14 +595,7 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
590595 typ = current .Type ()
591596
592597 if typ != timeType {
593-
594- // required passed validation above so stop here
595- // if only validating the structs existance.
596- if strings .Contains (tag , structOnlyTag ) {
597- return
598- }
599-
600- v .tranverseStruct (topStruct , current , current , errPrefix + name + "." , errs , false , partial , exclude , includeExclude )
598+ v .tranverseStruct (topStruct , current , current , errPrefix + name + "." , errs , false , partial , exclude , includeExclude , strings .Contains (tag , structOnlyTag ))
601599 return
602600 }
603601 }
0 commit comments