diff --git a/util/gvalid/gvalid_validator_check_map.go b/util/gvalid/gvalid_validator_check_map.go index 997706751..2e970b9eb 100644 --- a/util/gvalid/gvalid_validator_check_map.go +++ b/util/gvalid/gvalid_validator_check_map.go @@ -101,10 +101,10 @@ func (v *Validator) doCheckMap(ctx context.Context, params interface{}) Error { switch originTypeAndKind.OriginKind { case reflect.Map, reflect.Struct, reflect.Slice, reflect.Array: v.doCheckValueRecursively(ctx, doCheckValueRecursivelyInput{ - Value: item, - Type: originTypeAndKind.InputType, - OriginKind: originTypeAndKind.OriginKind, - ErrorMaps: errorMaps, + Value: item, + Type: originTypeAndKind.InputType, + Kind: originTypeAndKind.OriginKind, + ErrorMaps: errorMaps, }) } // Bail feature. diff --git a/util/gvalid/gvalid_validator_check_struct.go b/util/gvalid/gvalid_validator_check_struct.go index 42244db40..5b01b66a8 100644 --- a/util/gvalid/gvalid_validator_check_struct.go +++ b/util/gvalid/gvalid_validator_check_struct.go @@ -250,11 +250,11 @@ func (v *Validator) doCheckStruct(ctx context.Context, object interface{}) Error } switch field.OriginalKind() { case reflect.Map, reflect.Struct, reflect.Slice, reflect.Array: - // Recursively check attribute struct/[]string/map/[]map. + // Recursively check attribute slice/map. _, value = gutil.MapPossibleItemByKey(inputParamMap, field.Name()) v.doCheckValueRecursively(ctx, doCheckValueRecursivelyInput{ Value: value, - OriginKind: field.OriginalKind(), + Kind: field.OriginalKind(), Type: field.Type().Type, ErrorMaps: errorMaps, ResultSequenceRules: &resultSequenceRules, diff --git a/util/gvalid/gvalid_validator_check_value.go b/util/gvalid/gvalid_validator_check_value.go index bd69f9f77..0be8d29ed 100644 --- a/util/gvalid/gvalid_validator_check_value.go +++ b/util/gvalid/gvalid_validator_check_value.go @@ -540,13 +540,22 @@ func (v *Validator) doCheckSingleBuildInRules(ctx context.Context, in doCheckBui type doCheckValueRecursivelyInput struct { Value interface{} // Value to be validated. Type reflect.Type // Struct/map/slice type which to be recursively validated. - OriginKind reflect.Kind // Struct/map/slice kind to be asserted in following switch case. + Kind reflect.Kind // Struct/map/slice kind to be asserted in following switch case. ErrorMaps map[string]map[string]error // The validated failed error map. ResultSequenceRules *[]fieldRule // The validated failed rule in sequence. } func (v *Validator) doCheckValueRecursively(ctx context.Context, in doCheckValueRecursivelyInput) { - switch in.OriginKind { + switch in.Kind { + case reflect.Ptr: + v.doCheckValueRecursively(ctx, doCheckValueRecursivelyInput{ + Value: in.Value, + Type: in.Type.Elem(), + Kind: in.Type.Elem().Kind(), + ErrorMaps: in.ErrorMaps, + ResultSequenceRules: in.ResultSequenceRules, + }) + case reflect.Struct: // Ignore data, rules and messages from parent. validator := v.Clone() @@ -572,7 +581,7 @@ func (v *Validator) doCheckValueRecursively(ctx context.Context, in doCheckValue v.doCheckValueRecursively(ctx, doCheckValueRecursivelyInput{ Value: item, Type: mapTypeElem, - OriginKind: mapTypeKind, + Kind: mapTypeKind, ErrorMaps: in.ErrorMaps, ResultSequenceRules: in.ResultSequenceRules, }) @@ -596,7 +605,7 @@ func (v *Validator) doCheckValueRecursively(ctx context.Context, in doCheckValue v.doCheckValueRecursively(ctx, doCheckValueRecursivelyInput{ Value: item, Type: in.Type.Elem(), - OriginKind: in.Type.Elem().Kind(), + Kind: in.Type.Elem().Kind(), ErrorMaps: in.ErrorMaps, ResultSequenceRules: in.ResultSequenceRules, }) diff --git a/util/gvalid/gvalid_z_unit_feature_recursive_test.go b/util/gvalid/gvalid_z_unit_feature_recursive_test.go index 60401056c..b9dd51e0a 100755 --- a/util/gvalid/gvalid_z_unit_feature_recursive_test.go +++ b/util/gvalid/gvalid_z_unit_feature_recursive_test.go @@ -10,7 +10,6 @@ import ( "testing" "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/test/gtest" ) @@ -274,6 +273,27 @@ func Test_CheckStruct_Recursively_SliceAttribute(t *testing.T) { err := g.Validator().Assoc(data).Data(teacher).Run(ctx) t.Assert(err, `Student Name is required`) }) + + // https://github.com/gogf/gf/issues/1864 + gtest.C(t, func(t *gtest.T) { + type Student struct { + Name string `v:"required"` + Age int + } + type Teacher struct { + Name string + Students []*Student + } + var ( + teacher = Teacher{} + data = g.Map{ + "name": "john", + "students": `[{"age":2},{"name":"jack", "age":4}]`, + } + ) + err := g.Validator().Assoc(data).Data(teacher).Run(ctx) + t.Assert(err, `The Name field is required`) + }) } func Test_CheckStruct_Recursively_SliceAttribute_WithTypeAlias(t *testing.T) {