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. 2
      validator_test.go

@ -158,6 +158,9 @@ type FieldError interface {
// Error returns the FieldError's message // Error returns the FieldError's message
Error() string Error() string
// Parent returns the Type of the struct that the StructField is contained within
Parent() reflect.Type
} }
// compile time interface checks // compile time interface checks
@ -179,6 +182,7 @@ type fieldError struct {
param string param string
kind reflect.Kind kind reflect.Kind
typ reflect.Type typ reflect.Type
parent reflect.Type
} }
// Tag returns the validation tag that failed. // 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) 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 // Translate returns the FieldError's translated error
// from the provided 'ut.Translator' and registered 'TranslationFunc' // 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, param: ct.param,
kind: kind, kind: kind,
typ: current.Type(), typ: current.Type(),
parent: parent.Type(),
}, },
) )
return return
@ -199,6 +200,7 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr
param: ct.param, param: ct.param,
kind: kind, kind: kind,
typ: typ, typ: typ,
parent: parent.Type(),
}, },
) )
return return
@ -413,6 +415,7 @@ OUTER:
param: ct.param, param: ct.param,
kind: kind, kind: kind,
typ: typ, typ: typ,
parent: parent.Type(),
}, },
) )
@ -433,6 +436,7 @@ OUTER:
param: ct.param, param: ct.param,
kind: kind, kind: kind,
typ: typ, typ: typ,
parent: parent.Type(),
}, },
) )
} }
@ -474,6 +478,7 @@ OUTER:
param: ct.param, param: ct.param,
kind: kind, kind: kind,
typ: typ, typ: typ,
parent: parent.Type(),
}, },
) )

@ -367,6 +367,7 @@ func TestStructLevelInvalidError(t *testing.T) {
Equal(t, fe.ActualTag(), "required") Equal(t, fe.ActualTag(), "required")
Equal(t, fe.Kind(), reflect.Invalid) Equal(t, fe.Kind(), reflect.Invalid)
Equal(t, fe.Type(), reflect.TypeOf(nil)) Equal(t, fe.Type(), reflect.TypeOf(nil))
Equal(t, fe.Parent(), reflect.TypeOf(nil))
} }
func TestNameNamespace(t *testing.T) { func TestNameNamespace(t *testing.T) {
@ -8624,6 +8625,7 @@ func TestStructSliceValidation(t *testing.T) {
Equal(t, fe.Param(), "10") Equal(t, fe.Param(), "10")
Equal(t, fe.Kind(), reflect.Slice) Equal(t, fe.Kind(), reflect.Slice)
Equal(t, fe.Type(), reflect.TypeOf([]int{})) Equal(t, fe.Type(), reflect.TypeOf([]int{}))
Equal(t, fe.Parent(), reflect.TypeOf(TestSlice{}))
_, ok := fe.Value().([]int) _, ok := fe.Value().([]int)
Equal(t, ok, true) Equal(t, ok, true)

Loading…
Cancel
Save