diff --git a/validator.go b/validator.go index 049be60..e6e0cb9 100644 --- a/validator.go +++ b/validator.go @@ -199,12 +199,13 @@ type FieldError struct { Type reflect.Type Param string Value interface{} - isPlaceholderErr bool + IsPlaceholderErr bool IsSliceOrArray bool IsMap bool // Key interface{} // Index int - SliceOrArrayErrs []error // counld be FieldError, StructErrors + // SliceOrArrayErrs []error // counld be FieldError, StructErrors + SliceOrArrayErrs map[int]error // counld be FieldError, StructErrors MapErrs map[interface{}]error // counld be FieldError, StructErrors } @@ -707,7 +708,7 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f Kind: cField.kind, Type: cField.typ, Value: f, - isPlaceholderErr: true, + IsPlaceholderErr: true, IsSliceOrArray: true, // Index: i, SliceOrArrayErrs: errs, @@ -750,9 +751,9 @@ func (v *Validate) fieldWithNameAndValue(val interface{}, current interface{}, f return nil } -func (v *Validate) traverseSliceOrArray(val interface{}, current interface{}, valueField reflect.Value, cField *cachedField) []error { +func (v *Validate) traverseSliceOrArray(val interface{}, current interface{}, valueField reflect.Value, cField *cachedField) map[int]error { - errs := make([]error, 0) + errs := make(map[int]error, 0) for i := 0; i < valueField.Len(); i++ { @@ -764,7 +765,7 @@ func (v *Validate) traverseSliceOrArray(val interface{}, current interface{}, va if cField.isTimeSubtype || idxField.Type() == reflect.TypeOf(time.Time{}) { if fieldError := v.fieldWithNameAndValue(val, current, idxField.Interface(), cField.diveTag, cField.name, true, nil); fieldError != nil { - errs = append(errs, fieldError) + errs[i] = fieldError } continue @@ -778,25 +779,25 @@ func (v *Validate) traverseSliceOrArray(val interface{}, current interface{}, va if strings.Contains(cField.tag, required) { - errs = append(errs, &FieldError{ + errs[i] = &FieldError{ Field: cField.name, Tag: required, Value: idxField.Interface(), Kind: reflect.Ptr, Type: cField.sliceSubtype, - }) + } continue } } if structErrors := v.structRecursive(val, current, idxField.Interface()); structErrors != nil { - errs = append(errs, structErrors) + errs[i] = structErrors } default: if fieldError := v.fieldWithNameAndValue(val, current, idxField.Interface(), cField.diveTag, cField.name, true, nil); fieldError != nil { - errs = append(errs, fieldError) + errs[i] = fieldError } } } diff --git a/validator_test.go b/validator_test.go index 804babf..a32d99e 100644 --- a/validator_test.go +++ b/validator_test.go @@ -237,8 +237,42 @@ func TestArrayDiveValidation(t *testing.T) { } errs := validate.Struct(test) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldErr, ok := errs.Errors["Errs"] + Equal(t, ok, true) + Equal(t, fieldErr.IsPlaceholderErr, true) + Equal(t, fieldErr.IsSliceOrArray, true) + Equal(t, len(fieldErr.SliceOrArrayErrs), 1) + + innerErr, ok := fieldErr.SliceOrArrayErrs[1].(*FieldError) + Equal(t, ok, true) + Equal(t, innerErr.Tag, required) + Equal(t, innerErr.IsPlaceholderErr, false) + Equal(t, innerErr.Field, "Errs") + + test = &Test{ + Errs: []string{"ok", "ok", ""}, + } + + errs = validate.Struct(test) + NotEqual(t, errs, nil) + Equal(t, len(errs.Errors), 1) + + fieldErr, ok = errs.Errors["Errs"] + Equal(t, ok, true) + Equal(t, fieldErr.IsPlaceholderErr, true) + Equal(t, fieldErr.IsSliceOrArray, true) + Equal(t, len(fieldErr.SliceOrArrayErrs), 1) + + innerErr, ok = fieldErr.SliceOrArrayErrs[2].(*FieldError) + Equal(t, ok, true) + Equal(t, innerErr.Tag, required) + Equal(t, innerErr.IsPlaceholderErr, false) + Equal(t, innerErr.Field, "Errs") - fmt.Println(errs) + fmt.Println(errs.Errors["Errs"].IsPlaceholderErr) // type TestMap struct { // Errs *map[int]string `validate:"gt=0,dive,required"`