mirror of
https://github.com/romdo/go-validate.git
synced 2026-02-19 08:06:40 +00:00
fix(validate): do not panic with field errors on non-struct types
When validating non-struct types, we should not try and convert field values in errors, because there is no struct field to lookup. Hence this fix stops a panic from happening. It is up to the Validate() method itself to provide the correct and final field value when validating non-struct types.
This commit is contained in:
@@ -2,6 +2,7 @@ package validate_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -40,6 +41,29 @@ func (s *validatableStruct) Validate() error {
|
|||||||
return s.f()
|
return s.f()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type validatableSlice []validatableStruct
|
||||||
|
|
||||||
|
func (s validatableSlice) Validate() error {
|
||||||
|
var errs error
|
||||||
|
|
||||||
|
if len(s) < 1 {
|
||||||
|
errs = validate.AppendError(errs, "must contain at least 1 item")
|
||||||
|
}
|
||||||
|
|
||||||
|
fooVals := map[string]bool{}
|
||||||
|
for i, item := range s {
|
||||||
|
if fooVals[item.Foo] {
|
||||||
|
errs = validate.Append(errs, &validate.Error{
|
||||||
|
Field: fmt.Sprintf("%d.Foo", i),
|
||||||
|
Msg: "is not unique",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fooVals[item.Foo] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return errs
|
||||||
|
}
|
||||||
|
|
||||||
type nestedStruct struct {
|
type nestedStruct struct {
|
||||||
OtherField *validatableStruct
|
OtherField *validatableStruct
|
||||||
OtherFieldJSON *validatableStruct `json:"other_field,omitempty"`
|
OtherFieldJSON *validatableStruct `json:"other_field,omitempty"`
|
||||||
@@ -122,6 +146,31 @@ func TestValidate(t *testing.T) {
|
|||||||
&validate.Error{Msg: "must not contain space"},
|
&validate.Error{Msg: "must not contain space"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "valid validatable slice type",
|
||||||
|
obj: validatableSlice{
|
||||||
|
{Foo: "Hello"},
|
||||||
|
{Foo: "World"},
|
||||||
|
},
|
||||||
|
wantErrs: []error{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid validatable slice type",
|
||||||
|
obj: validatableSlice{},
|
||||||
|
wantErrs: []error{
|
||||||
|
&validate.Error{Msg: "must contain at least 1 item"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid validatable slice type with custom field error",
|
||||||
|
obj: validatableSlice{
|
||||||
|
{Foo: "Hello"},
|
||||||
|
{Foo: "Hello"},
|
||||||
|
},
|
||||||
|
wantErrs: []error{
|
||||||
|
&validate.Error{Field: "1.Foo", Msg: "is not unique"},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "single Go error",
|
name: "single Go error",
|
||||||
obj: &validatableStruct{f: func() error {
|
obj: &validatableStruct{f: func() error {
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ func (s *Validator) validate(path []string, data interface{}) error {
|
|||||||
e := &Error{}
|
e := &Error{}
|
||||||
if ok := errors.As(err, &e); ok {
|
if ok := errors.As(err, &e); ok {
|
||||||
field := e.Field
|
field := e.Field
|
||||||
if field != "" {
|
if field != "" && d.Kind() == reflect.Struct {
|
||||||
if sf, ok := d.Type().FieldByName(e.Field); ok {
|
if sf, ok := d.Type().FieldByName(e.Field); ok {
|
||||||
field = s.fieldName(sf)
|
field = s.fieldName(sf)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user