diff --git a/errors.go b/errors.go index 9a1b1ab..91b16fc 100644 --- a/errors.go +++ b/errors.go @@ -158,6 +158,9 @@ type FieldError interface { // Error returns the FieldError's message Error() string + + // Parent returns the Type of the struct that the StructField is contained within + Parent() reflect.Type } // compile time interface checks @@ -179,6 +182,7 @@ type fieldError struct { param string kind reflect.Kind typ reflect.Type + parent reflect.Type } // Tag returns the validation tag that failed. @@ -254,6 +258,11 @@ func (fe *fieldError) Error() string { return fmt.Sprintf(fieldErrMsg, fe.ns, fe.Field(), fe.tag) } +// Parent returns the Type of the struct that the StructField is contained within +func (fe *fieldError) Parent() reflect.Type { + return fe.parent +} + // Translate returns the FieldError's translated error // from the provided 'ut.Translator' and registered 'TranslationFunc' // diff --git a/validator.go b/validator.go index 80da095..3a7a8e2 100644 --- a/validator.go +++ b/validator.go @@ -154,6 +154,7 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr param: ct.param, kind: kind, typ: current.Type(), + parent: parent.Type(), }, ) return @@ -199,6 +200,7 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr param: ct.param, kind: kind, typ: typ, + parent: parent.Type(), }, ) return @@ -413,6 +415,7 @@ OUTER: param: ct.param, kind: kind, typ: typ, + parent: parent.Type(), }, ) @@ -433,6 +436,7 @@ OUTER: param: ct.param, kind: kind, typ: typ, + parent: parent.Type(), }, ) } @@ -474,6 +478,7 @@ OUTER: param: ct.param, kind: kind, typ: typ, + parent: parent.Type(), }, ) diff --git a/validator_test.go b/validator_test.go index 1ebdea5..62d4331 100644 --- a/validator_test.go +++ b/validator_test.go @@ -367,6 +367,7 @@ func TestStructLevelInvalidError(t *testing.T) { Equal(t, fe.ActualTag(), "required") Equal(t, fe.Kind(), reflect.Invalid) Equal(t, fe.Type(), reflect.TypeOf(nil)) + Equal(t, fe.Parent(), reflect.TypeOf(nil)) } func TestNameNamespace(t *testing.T) { @@ -8624,6 +8625,7 @@ func TestStructSliceValidation(t *testing.T) { Equal(t, fe.Param(), "10") Equal(t, fe.Kind(), reflect.Slice) Equal(t, fe.Type(), reflect.TypeOf([]int{})) + Equal(t, fe.Parent(), reflect.TypeOf(TestSlice{})) _, ok := fe.Value().([]int) Equal(t, ok, true) @@ -12264,25 +12266,25 @@ func TestCreditCardFormatValidation(t *testing.T) { } func TestMultiOrOperatorGroup(t *testing.T) { - tests := []struct { - Value int `validate:"eq=1|gte=5,eq=1|lt=7"` - expected bool - }{ - {1, true}, {2, false}, {5, true}, {6, true}, {8, false}, - } - - validate := New() - - for i, test := range tests { - errs := validate.Struct(test) - if test.expected { - if !IsEqual(errs, nil) { - t.Fatalf("Index: %d multi_group_of_OR_operators failed Error: %s", i, errs) - } - } else { - if IsEqual(errs, nil) { - t.Fatalf("Index: %d multi_group_of_OR_operators should have errs", i) - } - } - } - } + tests := []struct { + Value int `validate:"eq=1|gte=5,eq=1|lt=7"` + expected bool + }{ + {1, true}, {2, false}, {5, true}, {6, true}, {8, false}, + } + + validate := New() + + for i, test := range tests { + errs := validate.Struct(test) + if test.expected { + if !IsEqual(errs, nil) { + t.Fatalf("Index: %d multi_group_of_OR_operators failed Error: %s", i, errs) + } + } else { + if IsEqual(errs, nil) { + t.Fatalf("Index: %d multi_group_of_OR_operators should have errs", i) + } + } + } +}