Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ Here is a list of the current built in validators:
you know the struct will be valid, but need to verify it has been assigned.
NOTE: only "required" and "omitempty" can be used on a struct itself.

nostructlevel
Same as structonly tag except that any struct level validations will not run.

exists
Is a special tag without a validation function attached. It is used when a field
is a Pointer, Interface or Invalid and you wish to validate that it exists.
Expand Down
1 change: 1 addition & 0 deletions util.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var (
skipValidationTag: emptyStructPtr,
utf8HexComma: emptyStructPtr,
utf8Pipe: emptyStructPtr,
noStructLevelTag: emptyStructPtr,
}
)

Expand Down
6 changes: 6 additions & 0 deletions validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const (
orSeparator = "|"
tagKeySeparator = "="
structOnlyTag = "structonly"
noStructLevelTag = "nostructlevel"
omitempty = "omitempty"
skipValidationTag = "-"
diveTag = "dive"
Expand Down Expand Up @@ -595,6 +596,11 @@ func (v *Validate) traverseField(topStruct reflect.Value, currentStruct reflect.
typ = current.Type()

if typ != timeType {

if strings.Contains(tag, noStructLevelTag) {
return
}

v.tranverseStruct(topStruct, current, current, errPrefix+name+".", errs, false, partial, exclude, includeExclude, strings.Contains(tag, structOnlyTag))
return
}
Expand Down
31 changes: 31 additions & 0 deletions validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3493,6 +3493,36 @@ func TestBase64Validation(t *testing.T) {
AssertError(t, errs, "", "", "base64")
}

func TestNoStructLevelValidation(t *testing.T) {

type Inner struct {
Test string `validate:"len=5"`
}

type Outer struct {
InnerStruct *Inner `validate:"required,nostructlevel"`
}

outer := &Outer{
InnerStruct: nil,
}

errs := validate.Struct(outer)
NotEqual(t, errs, nil)
AssertError(t, errs, "Outer.InnerStruct", "InnerStruct", "required")

inner := &Inner{
Test: "1234",
}

outer = &Outer{
InnerStruct: inner,
}

errs = validate.Struct(outer)
Equal(t, errs, nil)
}

func TestStructOnlyValidation(t *testing.T) {

type Inner struct {
Expand All @@ -3509,6 +3539,7 @@ func TestStructOnlyValidation(t *testing.T) {

errs := validate.Struct(outer)
NotEqual(t, errs, nil)
AssertError(t, errs, "Outer.InnerStruct", "InnerStruct", "required")

inner := &Inner{
Test: "1234",
Expand Down