Merge pull request #81 from bluesuncorp/v5-development

Fix Issue with nested struct as pointer being nil
pull/84/head v5.8.1
Dean Karn 10 years ago
commit 27a1d3f158
  1. 19
      validator.go
  2. 99
      validator_test.go

@ -27,6 +27,7 @@ const (
tagKeySeparator = "=" tagKeySeparator = "="
structOnlyTag = "structonly" structOnlyTag = "structonly"
omitempty = "omitempty" omitempty = "omitempty"
required = "required"
fieldErrMsg = "Field validation for \"%s\" failed on the \"%s\" tag" fieldErrMsg = "Field validation for \"%s\" failed on the \"%s\" tag"
structErrMsg = "Struct:%s\n" structErrMsg = "Struct:%s\n"
) )
@ -390,6 +391,24 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
continue continue
} }
if valueField.Kind() == reflect.Ptr && valueField.IsNil() {
if strings.Contains(cField.tag, omitempty) {
continue
}
if strings.Contains(cField.tag, required) {
validationErrors.Errors[cField.name] = &FieldError{
Field: cField.name,
Tag: required,
Value: valueField.Interface(),
}
continue
}
}
if structErrors := v.structRecursive(top, valueField.Interface(), valueField.Interface()); structErrors != nil { if structErrors := v.structRecursive(top, valueField.Interface(), valueField.Interface()); structErrors != nil {
validationErrors.StructErrors[cField.name] = structErrors validationErrors.StructErrors[cField.name] = structErrors
// free up memory map no longer needed // free up memory map no longer needed

@ -226,6 +226,98 @@ func AssertMapFieldError(t *testing.T, s map[string]*FieldError, field string, e
EqualSkip(t, 2, val.Tag, expectedTag) EqualSkip(t, 2, val.Tag, expectedTag)
} }
func TestNilStructPointerValidation(t *testing.T) {
type Inner struct {
Data string
}
type Outer struct {
Inner *Inner `validate:"omitempty"`
}
inner := &Inner{
Data: "test",
}
outer := &Outer{
Inner: inner,
}
errs := validate.Struct(outer)
Equal(t, errs, nil)
outer = &Outer{
Inner: nil,
}
errs = validate.Struct(outer)
Equal(t, errs, nil)
type Inner2 struct {
Data string
}
type Outer2 struct {
Inner2 *Inner2 `validate:"required"`
}
inner2 := &Inner2{
Data: "test",
}
outer2 := &Outer2{
Inner2: inner2,
}
errs = validate.Struct(outer2)
Equal(t, errs, nil)
outer2 = &Outer2{
Inner2: nil,
}
errs = validate.Struct(outer2)
NotEqual(t, errs, nil)
type Inner3 struct {
Data string
}
type Outer3 struct {
Inner3 *Inner3
}
inner3 := &Inner3{
Data: "test",
}
outer3 := &Outer3{
Inner3: inner3,
}
errs = validate.Struct(outer3)
Equal(t, errs, nil)
type Inner4 struct {
Data string
}
type Outer4 struct {
Inner4 *Inner4 `validate:"-"`
}
inner4 := &Inner4{
Data: "test",
}
outer4 := &Outer4{
Inner4: inner4,
}
errs = validate.Struct(outer4)
Equal(t, errs, nil)
}
func TestSSNValidation(t *testing.T) { func TestSSNValidation(t *testing.T) {
tests := []struct { tests := []struct {
param string param string
@ -1100,7 +1192,7 @@ func TestStructOnlyValidation(t *testing.T) {
InnerStruct: nil, InnerStruct: nil,
} }
errs := validate.Struct(outer).Flatten() errs := validate.Struct(outer)
NotEqual(t, errs, nil) NotEqual(t, errs, nil)
inner := &Inner{ inner := &Inner{
@ -1111,9 +1203,8 @@ func TestStructOnlyValidation(t *testing.T) {
InnerStruct: inner, InnerStruct: inner,
} }
errs = validate.Struct(outer).Flatten() errs = validate.Struct(outer)
NotEqual(t, errs, nil) Equal(t, errs, nil)
Equal(t, len(errs), 0)
} }
func TestGtField(t *testing.T) { func TestGtField(t *testing.T) {

Loading…
Cancel
Save