Skip to content

Commit e078205

Browse files
joeybloggsjoeybloggs
authored andcommitted
Update Required & Invalid logic
updated required validator to check for a nil value for types: slice, map, pointer, interface, channel and function. updated tranverseField to handle invalid field type. Changes to be committed: modified: baked_in.go modified: doc.go modified: validator.go modified: validator_test.go
1 parent ea0db1f commit e078205

File tree

4 files changed

+98
-12
lines changed

4 files changed

+98
-12
lines changed

baked_in.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -403,10 +403,8 @@ func isAlpha(topStruct reflect.Value, currentStruct reflect.Value, field reflect
403403
func hasValue(topStruct reflect.Value, currentStruct reflect.Value, field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string) bool {
404404

405405
switch fieldKind {
406-
407-
case reflect.Slice, reflect.Map, reflect.Array:
408-
return !field.IsNil() && int64(field.Len()) > 0
409-
406+
case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
407+
return !field.IsNil()
410408
default:
411409
return field.IsValid() && field.Interface() != reflect.Zero(fieldType).Interface()
412410
}

doc.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,10 @@ Here is a list of the current built in validators:
123123
required will be applied to string
124124
125125
required
126-
This validates that the value is not the data types default value.
126+
This validates that the value is not the data types default zero value.
127127
For numbers ensures value is not zero. For strings ensures value is
128-
not "". For slices, arrays, and maps, ensures the length is not zero.
128+
not "". For slices, maps, pointers, interfaces, channels and functions
129+
ensures the value is not nil.
129130
(Usage: required)
130131
131132
len

validator.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,12 +243,10 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
243243
kind = current.Kind()
244244
}
245245

246-
typ := current.Type()
247-
248246
// this also allows for tags 'required' and 'omitempty' to be used on
249247
// nested struct fields because when len(tags) > 0 below and the value is nil
250248
// then required failes and we check for omitempty just before that
251-
if (kind == reflect.Ptr || kind == reflect.Interface) && current.IsNil() {
249+
if ((kind == reflect.Ptr || kind == reflect.Interface) && current.IsNil()) || kind == reflect.Invalid {
252250

253251
if strings.Contains(tag, omitempty) {
254252
return
@@ -264,19 +262,35 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
264262
param = vals[1]
265263
}
266264

265+
if kind == reflect.Invalid {
266+
errs[errPrefix+name] = &FieldError{
267+
Field: name,
268+
Tag: vals[0],
269+
Param: param,
270+
Kind: kind,
271+
}
272+
return
273+
}
274+
267275
errs[errPrefix+name] = &FieldError{
268276
Field: name,
269277
Tag: vals[0],
270278
Param: param,
271279
Value: current.Interface(),
272280
Kind: kind,
273-
Type: typ,
281+
Type: current.Type(),
274282
}
275283

276284
return
277285
}
286+
// if we get here tag length is zero and we can leave
287+
if kind == reflect.Invalid {
288+
return
289+
}
278290
}
279291

292+
typ := current.Type()
293+
280294
switch kind {
281295
case reflect.Struct, reflect.Interface:
282296

validator_test.go

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,79 @@ func AssertError(t *testing.T, errs ValidationErrors, key, field, expectedTag st
119119
EqualSkip(t, 2, val.Tag, expectedTag)
120120
}
121121

122+
func TestSliceMapArrayChanFuncPtrInterfaceRequiredValidation(t *testing.T) {
123+
124+
var m map[string]string
125+
126+
errs := validate.Field(m, "required")
127+
NotEqual(t, errs, nil)
128+
AssertError(t, errs, "", "", "required")
129+
130+
m = map[string]string{}
131+
errs = validate.Field(m, "required")
132+
Equal(t, errs, nil)
133+
134+
var arr [5]string
135+
errs = validate.Field(arr, "required")
136+
NotEqual(t, errs, nil)
137+
AssertError(t, errs, "", "", "required")
138+
139+
arr[0] = "ok"
140+
errs = validate.Field(arr, "required")
141+
Equal(t, errs, nil)
142+
143+
var s []string
144+
errs = validate.Field(s, "required")
145+
NotEqual(t, errs, nil)
146+
AssertError(t, errs, "", "", "required")
147+
148+
s = []string{}
149+
errs = validate.Field(s, "required")
150+
Equal(t, errs, nil)
151+
152+
var c chan string
153+
errs = validate.Field(c, "required")
154+
NotEqual(t, errs, nil)
155+
AssertError(t, errs, "", "", "required")
156+
157+
c = make(chan string)
158+
errs = validate.Field(c, "required")
159+
Equal(t, errs, nil)
160+
161+
var tst *int
162+
errs = validate.Field(tst, "required")
163+
NotEqual(t, errs, nil)
164+
AssertError(t, errs, "", "", "required")
165+
166+
one := 1
167+
tst = &one
168+
errs = validate.Field(tst, "required")
169+
Equal(t, errs, nil)
170+
171+
var iface interface{}
172+
173+
errs = validate.Field(iface, "required")
174+
NotEqual(t, errs, nil)
175+
AssertError(t, errs, "", "", "required")
176+
177+
errs = validate.Field(iface, "omitempty,required")
178+
Equal(t, errs, nil)
179+
180+
errs = validate.Field(iface, "")
181+
Equal(t, errs, nil)
182+
183+
var f func(string)
184+
185+
errs = validate.Field(f, "required")
186+
NotEqual(t, errs, nil)
187+
AssertError(t, errs, "", "", "required")
188+
189+
f = func(name string) {}
190+
191+
errs = validate.Field(f, "required")
192+
Equal(t, errs, nil)
193+
}
194+
122195
func TestDatePtrValidationIssueValidation(t *testing.T) {
123196

124197
type Test struct {
@@ -3262,14 +3335,14 @@ func TestStructSliceValidation(t *testing.T) {
32623335
Min: []int{1, 2},
32633336
Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0},
32643337
MinMax: []int{1, 2, 3, 4, 5},
3265-
OmitEmpty: []int{},
3338+
OmitEmpty: nil,
32663339
}
32673340

32683341
errs := validate.Struct(tSuccess)
32693342
Equal(t, errs, nil)
32703343

32713344
tFail := &TestSlice{
3272-
Required: []int{},
3345+
Required: nil,
32733346
Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
32743347
Min: []int{},
32753348
Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},

0 commit comments

Comments
 (0)