diff --git a/baked_in.go b/baked_in.go index 0fae541..965c651 100644 --- a/baked_in.go +++ b/baked_in.go @@ -63,6 +63,7 @@ var ( // or even disregard and use your own map if so desired. bakedInValidators = map[string]Func{ "required": hasValue, + "notblank": notBlank, "isdefault": isDefault, "len": hasLengthOf, "min": hasMinOf, @@ -1264,6 +1265,20 @@ func hasValue(fl FieldLevel) bool { } } +// NotBlank is the validation function for validating if the current field has a value or length greater than zero. +func notBlank(fl FieldLevel) bool { + field := fl.Field() + + switch field.Kind() { + case reflect.String: + return len(strings.TrimSpace(field.String())) > 0 + case reflect.Chan, reflect.Map, reflect.Slice, reflect.Array: + return field.Len() > 0 + default: + return hasValue(fl) + } +} + // IsGteField is the validation function for validating if the current field's value is greater than or equal to the field specified by the param's value. func isGteField(fl FieldLevel) bool { diff --git a/validator_test.go b/validator_test.go index 5534aa5..69724c1 100644 --- a/validator_test.go +++ b/validator_test.go @@ -62,6 +62,7 @@ type TestInterface struct { type TestString struct { BlankTag string `validate:""` Required string `validate:"required"` + NotBlank string `validate:"notblank"` Len string `validate:"len=10"` Min string `validate:"min=1"` Max string `validate:"max=10"` @@ -81,6 +82,7 @@ type TestString struct { type TestUint64 struct { Required uint64 `validate:"required"` + NotBlank uint64 `validate:"notblank"` Len uint64 `validate:"len=10"` Min uint64 `validate:"min=1"` Max uint64 `validate:"max=10"` @@ -90,6 +92,7 @@ type TestUint64 struct { type TestFloat64 struct { Required float64 `validate:"required"` + NotBlank float64 `validate:"notblank"` Len float64 `validate:"len=10"` Min float64 `validate:"min=1"` Max float64 `validate:"max=10"` @@ -100,6 +103,7 @@ type TestFloat64 struct { type TestSlice struct { Required []int `validate:"required"` + NotBlank []int `validate:"notblank"` Len []int `validate:"len=10"` Min []int `validate:"min=1"` Max []int `validate:"max=10"` @@ -6725,6 +6729,7 @@ func TestStructStringValidation(t *testing.T) { tSuccess := &TestString{ Required: "Required", + NotBlank: "NotBLank", Len: "length==10", Min: "min=1", Max: "1234567890", @@ -6755,6 +6760,7 @@ func TestStructStringValidation(t *testing.T) { tFail := &TestString{ Required: "", + NotBlank: " ", Len: "", Min: "", Max: "12345678901", @@ -6781,10 +6787,11 @@ func TestStructStringValidation(t *testing.T) { // Assert Top Level NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 13) + Equal(t, len(errs.(ValidationErrors)), 14) // Assert Fields AssertError(t, errs, "TestString.Required", "TestString.Required", "Required", "Required", "required") + AssertError(t, errs, "TestString.NotBlank", "TestString.NotBlank", "NotBlank", "NotBlank", "notblank") AssertError(t, errs, "TestString.Len", "TestString.Len", "Len", "Len", "len") AssertError(t, errs, "TestString.Min", "TestString.Min", "Min", "Min", "min") AssertError(t, errs, "TestString.Max", "TestString.Max", "Max", "Max", "max") @@ -6805,6 +6812,7 @@ func TestStructInt32Validation(t *testing.T) { type TestInt32 struct { Required int `validate:"required"` + NotBlank int `validate:"notblank"` Len int `validate:"len=10"` Min int `validate:"min=1"` Max int `validate:"max=10"` @@ -6818,6 +6826,7 @@ func TestStructInt32Validation(t *testing.T) { tSuccess := &TestInt32{ Required: 1, + NotBlank: 1, Len: 10, Min: 1, Max: 10, @@ -6835,6 +6844,7 @@ func TestStructInt32Validation(t *testing.T) { tFail := &TestInt32{ Required: 0, + NotBlank: 0, Len: 11, Min: -1, Max: 11, @@ -6850,10 +6860,11 @@ func TestStructInt32Validation(t *testing.T) { // Assert Top Level NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 10) + Equal(t, len(errs.(ValidationErrors)), 11) // Assert Fields AssertError(t, errs, "TestInt32.Required", "TestInt32.Required", "Required", "Required", "required") + AssertError(t, errs, "TestInt32.NotBlank", "TestInt32.NotBlank", "NotBlank", "NotBlank", "notblank") AssertError(t, errs, "TestInt32.Len", "TestInt32.Len", "Len", "Len", "len") AssertError(t, errs, "TestInt32.Min", "TestInt32.Min", "Min", "Min", "min") AssertError(t, errs, "TestInt32.Max", "TestInt32.Max", "Max", "Max", "max") @@ -6871,6 +6882,7 @@ func TestStructUint64Validation(t *testing.T) { tSuccess := &TestUint64{ Required: 1, + NotBlank: 1, Len: 10, Min: 1, Max: 10, @@ -6883,6 +6895,7 @@ func TestStructUint64Validation(t *testing.T) { tFail := &TestUint64{ Required: 0, + NotBlank: 0, Len: 11, Min: 0, Max: 11, @@ -6894,10 +6907,11 @@ func TestStructUint64Validation(t *testing.T) { // Assert Top Level NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 6) + Equal(t, len(errs.(ValidationErrors)), 7) // Assert Fields AssertError(t, errs, "TestUint64.Required", "TestUint64.Required", "Required", "Required", "required") + AssertError(t, errs, "TestUint64.NotBlank", "TestUint64.NotBlank", "NotBlank", "NotBlank", "notblank") AssertError(t, errs, "TestUint64.Len", "TestUint64.Len", "Len", "Len", "len") AssertError(t, errs, "TestUint64.Min", "TestUint64.Min", "Min", "Min", "min") AssertError(t, errs, "TestUint64.Max", "TestUint64.Max", "Max", "Max", "max") @@ -6911,6 +6925,7 @@ func TestStructFloat64Validation(t *testing.T) { tSuccess := &TestFloat64{ Required: 1, + NotBlank: 1, Len: 10, Min: 1, Max: 10, @@ -6923,6 +6938,7 @@ func TestStructFloat64Validation(t *testing.T) { tFail := &TestFloat64{ Required: 0, + NotBlank: 0, Len: 11, Min: 0, Max: 11, @@ -6934,10 +6950,11 @@ func TestStructFloat64Validation(t *testing.T) { // Assert Top Level NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 6) + Equal(t, len(errs.(ValidationErrors)), 7) // Assert Fields AssertError(t, errs, "TestFloat64.Required", "TestFloat64.Required", "Required", "Required", "required") + AssertError(t, errs, "TestFloat64.NotBlank", "TestFloat64.NotBlank", "NotBlank", "NotBlank", "notblank") AssertError(t, errs, "TestFloat64.Len", "TestFloat64.Len", "Len", "Len", "len") AssertError(t, errs, "TestFloat64.Min", "TestFloat64.Min", "Min", "Min", "min") AssertError(t, errs, "TestFloat64.Max", "TestFloat64.Max", "Max", "Max", "max") @@ -6951,6 +6968,7 @@ func TestStructSliceValidation(t *testing.T) { tSuccess := &TestSlice{ Required: []int{1}, + NotBlank: []int{1}, Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, Min: []int{1, 2}, Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, @@ -6963,6 +6981,7 @@ func TestStructSliceValidation(t *testing.T) { tFail := &TestSlice{ Required: nil, + NotBlank: []int{}, Len: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1}, Min: []int{}, Max: []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1}, @@ -6972,7 +6991,7 @@ func TestStructSliceValidation(t *testing.T) { errs = validate.Struct(tFail) NotEqual(t, errs, nil) - Equal(t, len(errs.(ValidationErrors)), 6) + Equal(t, len(errs.(ValidationErrors)), 7) // Assert Field Errors AssertError(t, errs, "TestSlice.Required", "TestSlice.Required", "Required", "Required", "required")