Enhanced ValidationCtx method to support nested map in slice #915 (#917)

pull/936/head
Jason.Zhang 2 years ago committed by GitHub
parent 99922fccc7
commit d3e4be3e44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      _examples/map-validation/main.go
  2. 25
      validator_instance.go
  3. 91
      validator_test.go

@ -48,6 +48,16 @@ func validateNestedMap() {
"mother_name": "Hannah",
},
"salary": "1000",
"phones": []map[string]interface{}{
{
"number": "11-111-1111",
"remark": "home",
},
{
"number": "22-222-2222",
"remark": "work",
},
},
},
}
@ -62,6 +72,10 @@ func validateNestedMap() {
"mother_name": "required,min=4,max=32",
},
"salary": "number",
"phones": map[string]interface{}{
"number": "required,min=4,max=32",
"remark": "required,min=1,max=32",
},
},
}

@ -154,15 +154,24 @@ 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 {
err := v.ValidateMapCtx(ctx, data[field].(map[string]interface{}), rule.(map[string]interface{}))
if len(err) > 0 {
errs[field] = err
if ruleObj, ok := rule.(map[string]interface{}); ok {
if dataObj, ok := data[field].(map[string]interface{}); ok {
err := v.ValidateMapCtx(ctx, dataObj, ruleObj)
if len(err) > 0 {
errs[field] = err
}
} else if dataObjs, ok := data[field].([]map[string]interface{}); ok {
for _, obj := range dataObjs {
err := v.ValidateMapCtx(ctx, obj, ruleObj)
if len(err) > 0 {
errs[field] = err
}
}
} else {
errs[field] = errors.New("The field: '" + field + "' is not a map to dive")
}
} 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))
} else if ruleStr, ok := rule.(string); ok {
err := v.VarCtx(ctx, data[field], ruleStr)
if err != nil {
errs[field] = err
}

@ -12134,6 +12134,97 @@ func TestPostCodeByIso3166Alpha2Field_InvalidKind(t *testing.T) {
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": []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": []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)
}
})
}
}
func TestCreditCardFormatValidation(t *testing.T) {
tests := []struct {
value string `validate:"credit_card"`

Loading…
Cancel
Save