From 24c1c6819f32b0048532f58bf103fc05bead2e98 Mon Sep 17 00:00:00 2001 From: joeybloggs Date: Thu, 19 Nov 2015 16:43:52 -0500 Subject: [PATCH] Add nostructlevel tag * nostructlevel - Same as structonly tag except that any struct level validations will not run. --- doc.go | 3 +++ util.go | 1 + validator.go | 6 ++++++ validator_test.go | 31 +++++++++++++++++++++++++++++++ 4 files changed, 41 insertions(+) diff --git a/doc.go b/doc.go index fd7fc30..d084b83 100644 --- a/doc.go +++ b/doc.go @@ -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. diff --git a/util.go b/util.go index 6719787..4ba6ce5 100644 --- a/util.go +++ b/util.go @@ -26,6 +26,7 @@ var ( skipValidationTag: emptyStructPtr, utf8HexComma: emptyStructPtr, utf8Pipe: emptyStructPtr, + noStructLevelTag: emptyStructPtr, } ) diff --git a/validator.go b/validator.go index 49a0727..cf1ff21 100644 --- a/validator.go +++ b/validator.go @@ -26,6 +26,7 @@ const ( orSeparator = "|" tagKeySeparator = "=" structOnlyTag = "structonly" + noStructLevelTag = "nostructlevel" omitempty = "omitempty" skipValidationTag = "-" diveTag = "dive" @@ -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 } diff --git a/validator_test.go b/validator_test.go index b45a47f..be4a2a9 100644 --- a/validator_test.go +++ b/validator_test.go @@ -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 { @@ -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",