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.
pull/951/head
Will May 3 years ago
parent 9e2ea40380
commit 498124539d
  1. 9
      errors.go
  2. 5
      validator.go
  3. 46
      validator_test.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'
//

@ -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(),
},
)

@ -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)
}
}
}
}

Loading…
Cancel
Save