From 498124539d3c9a130bd3abdd9f597de33898cec8 Mon Sep 17 00:00:00 2001 From: Will May Date: Mon, 30 May 2022 08:46:32 +0100 Subject: [PATCH] Expose the struct the field is contained within This allows users of `FieldError` to be able to query information about the struct the field is contained within. This information can then be used to work out what to display when the param field points to another field, such as with `gtfield`, and a tag name function has been registered. --- errors.go | 9 +++++++++ validator.go | 5 +++++ validator_test.go | 46 ++++++++++++++++++++++++---------------------- 3 files changed, 38 insertions(+), 22 deletions(-) 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) + } + } + } +}