Skip to content

Commit

Permalink
Enhanced ValidationCtx method to support nested map in slice go-playg…
Browse files Browse the repository at this point in the history
  • Loading branch information
leftjs committed Mar 19, 2022
1 parent 58d5778 commit 3561a9c
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 8 deletions.
30 changes: 23 additions & 7 deletions validator_instance.go
Expand Up @@ -152,19 +152,35 @@ func (v *Validate) SetTagName(name string) {
func (v Validate) ValidateMapCtx(ctx context.Context, data map[string]interface{}, rules map[string]interface{}) map[string]interface{} {
errs := make(map[string]interface{})
for field, rule := range rules {
if reflect.ValueOf(rule).Kind() == reflect.Map && reflect.ValueOf(data[field]).Kind() == reflect.Map {
if reflect.ValueOf(rule).Kind() != reflect.Map {
err := v.VarCtx(ctx, data[field], rule.(string))
if err != nil {
errs[field] = err
}
continue
}

if kind := reflect.ValueOf(data[field]).Kind(); kind == reflect.Map {
err := v.ValidateMapCtx(ctx, data[field].(map[string]interface{}), rule.(map[string]interface{}))
if len(err) > 0 {
errs[field] = err
}
} else if reflect.ValueOf(rule).Kind() == reflect.Map {
errs[field] = errors.New("The field: '" + field + "' is not a map to dive")
} else {
err := v.VarCtx(ctx, data[field], rule.(string))
if err != nil {
errs[field] = err
} else if kind == reflect.Slice {
for _, item := range data[field].([]interface{}) {
if reflect.ValueOf(item).Kind() != reflect.Map {
errs[field] = errors.New("The field: '" + field + "' is not a []map to dive")
continue
}

err := v.ValidateMapCtx(ctx, item.(map[string]interface{}), rule.(map[string]interface{}))
if len(err) > 0 {
errs[field] = err
}
}
} else {
errs[field] = errors.New("The field: '" + field + "' is not a map to dive")
}

}
return errs
}
Expand Down
92 changes: 91 additions & 1 deletion validator_test.go
Expand Up @@ -11460,7 +11460,7 @@ func TestSemverFormatValidation(t *testing.T) {
}
}
}

func TestRFC1035LabelFormatValidation(t *testing.T) {
tests := []struct {
value string `validate:"dns_rfc1035_label"`
Expand Down Expand Up @@ -11611,3 +11611,93 @@ func TestPostCodeByIso3166Alpha2Field_InvalidKind(t *testing.T) {
_ = New().Struct(test{"ABC", 123, false})
t.Errorf("Didn't panic as expected")
}

func TestValidate_ValidateMapCtx(t *testing.T) {

type args struct {
data map[string]interface{}
rules map[string]interface{}
}
tests := []struct {
name string
args args
want int
}{
{
name: "test nested map in slice",
args: args{
data: map[string]interface{}{
"Test_A": map[string]interface{}{
"Test_B": "Test_B",
"Test_C": []interface{}{
map[string]interface{}{
"Test_D": "Test_D",
},
},
"Test_E": map[string]interface{}{
"Test_F": "Test_F",
},
},
},
rules: map[string]interface{}{
"Test_A": map[string]interface{}{
"Test_B": "min=2",
"Test_C": map[string]interface{}{
"Test_D": "min=2",
},
"Test_E": map[string]interface{}{
"Test_F": "min=2",
},
},
},
},
want: 0,
},

{
name: "test nested map error",
args: args{
data: map[string]interface{}{
"Test_A": map[string]interface{}{
"Test_B": "Test_B",
"Test_C": []interface{}{"Test_D"},
"Test_E": map[string]interface{}{
"Test_F": "Test_F",
},
"Test_G": "Test_G",
"Test_I": []interface{}{
map[string]interface{}{
"Test_J": "Test_J",
}},
},
},
rules: map[string]interface{}{
"Test_A": map[string]interface{}{
"Test_B": "min=2",
"Test_C": map[string]interface{}{
"Test_D": "min=2",
},
"Test_E": map[string]interface{}{
"Test_F": "min=100",
},
"Test_G": map[string]interface{}{
"Test_H": "min=2",
},
"Test_I": map[string]interface{}{
"Test_J": "min=100",
},
},
},
},
want: 1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
validate := New()
if got := validate.ValidateMapCtx(context.Background(), tt.args.data, tt.args.rules); len(got) != tt.want {
t.Errorf("ValidateMapCtx() = %#v, want %#v", got, tt.want)
}
})
}
}

0 comments on commit 3561a9c

Please sign in to comment.