Skip to content

Commit 27a1d3f

Browse files
Dean KarnDean Karn
authored andcommitted
Merge pull request #81 from bluesuncorp/v5-development
Fix Issue with nested struct as pointer being nil
2 parents c06d47f + 3e4207b commit 27a1d3f

File tree

2 files changed

+114
-4
lines changed

2 files changed

+114
-4
lines changed

validator.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const (
2727
tagKeySeparator = "="
2828
structOnlyTag = "structonly"
2929
omitempty = "omitempty"
30+
required = "required"
3031
fieldErrMsg = "Field validation for \"%s\" failed on the \"%s\" tag"
3132
structErrMsg = "Struct:%s\n"
3233
)
@@ -390,6 +391,24 @@ func (v *Validate) structRecursive(top interface{}, current interface{}, s inter
390391
continue
391392
}
392393

394+
if valueField.Kind() == reflect.Ptr && valueField.IsNil() {
395+
396+
if strings.Contains(cField.tag, omitempty) {
397+
continue
398+
}
399+
400+
if strings.Contains(cField.tag, required) {
401+
402+
validationErrors.Errors[cField.name] = &FieldError{
403+
Field: cField.name,
404+
Tag: required,
405+
Value: valueField.Interface(),
406+
}
407+
408+
continue
409+
}
410+
}
411+
393412
if structErrors := v.structRecursive(top, valueField.Interface(), valueField.Interface()); structErrors != nil {
394413
validationErrors.StructErrors[cField.name] = structErrors
395414
// free up memory map no longer needed

validator_test.go

Lines changed: 95 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,98 @@ func AssertMapFieldError(t *testing.T, s map[string]*FieldError, field string, e
226226
EqualSkip(t, 2, val.Tag, expectedTag)
227227
}
228228

229+
func TestNilStructPointerValidation(t *testing.T) {
230+
type Inner struct {
231+
Data string
232+
}
233+
234+
type Outer struct {
235+
Inner *Inner `validate:"omitempty"`
236+
}
237+
238+
inner := &Inner{
239+
Data: "test",
240+
}
241+
242+
outer := &Outer{
243+
Inner: inner,
244+
}
245+
246+
errs := validate.Struct(outer)
247+
Equal(t, errs, nil)
248+
249+
outer = &Outer{
250+
Inner: nil,
251+
}
252+
253+
errs = validate.Struct(outer)
254+
Equal(t, errs, nil)
255+
256+
type Inner2 struct {
257+
Data string
258+
}
259+
260+
type Outer2 struct {
261+
Inner2 *Inner2 `validate:"required"`
262+
}
263+
264+
inner2 := &Inner2{
265+
Data: "test",
266+
}
267+
268+
outer2 := &Outer2{
269+
Inner2: inner2,
270+
}
271+
272+
errs = validate.Struct(outer2)
273+
Equal(t, errs, nil)
274+
275+
outer2 = &Outer2{
276+
Inner2: nil,
277+
}
278+
279+
errs = validate.Struct(outer2)
280+
NotEqual(t, errs, nil)
281+
282+
type Inner3 struct {
283+
Data string
284+
}
285+
286+
type Outer3 struct {
287+
Inner3 *Inner3
288+
}
289+
290+
inner3 := &Inner3{
291+
Data: "test",
292+
}
293+
294+
outer3 := &Outer3{
295+
Inner3: inner3,
296+
}
297+
298+
errs = validate.Struct(outer3)
299+
Equal(t, errs, nil)
300+
301+
type Inner4 struct {
302+
Data string
303+
}
304+
305+
type Outer4 struct {
306+
Inner4 *Inner4 `validate:"-"`
307+
}
308+
309+
inner4 := &Inner4{
310+
Data: "test",
311+
}
312+
313+
outer4 := &Outer4{
314+
Inner4: inner4,
315+
}
316+
317+
errs = validate.Struct(outer4)
318+
Equal(t, errs, nil)
319+
}
320+
229321
func TestSSNValidation(t *testing.T) {
230322
tests := []struct {
231323
param string
@@ -1100,7 +1192,7 @@ func TestStructOnlyValidation(t *testing.T) {
11001192
InnerStruct: nil,
11011193
}
11021194

1103-
errs := validate.Struct(outer).Flatten()
1195+
errs := validate.Struct(outer)
11041196
NotEqual(t, errs, nil)
11051197

11061198
inner := &Inner{
@@ -1111,9 +1203,8 @@ func TestStructOnlyValidation(t *testing.T) {
11111203
InnerStruct: inner,
11121204
}
11131205

1114-
errs = validate.Struct(outer).Flatten()
1115-
NotEqual(t, errs, nil)
1116-
Equal(t, len(errs), 0)
1206+
errs = validate.Struct(outer)
1207+
Equal(t, errs, nil)
11171208
}
11181209

11191210
func TestGtField(t *testing.T) {

0 commit comments

Comments
 (0)