From 684c339b0db3d9f1af1a05e5a9a657f0648fac67 Mon Sep 17 00:00:00 2001 From: Dean Karn Date: Thu, 19 Mar 2015 15:55:23 -0400 Subject: [PATCH 1/2] issue-#15 correct incorrect call to ValidateStruct and changed to ValidateStructRecursive --- validator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/validator.go b/validator.go index 32593d8..9ba8e24 100644 --- a/validator.go +++ b/validator.go @@ -216,7 +216,7 @@ func (v *Validator) validateStructRecursive(top interface{}, s interface{}) *Str } else { - if structErrors := v.ValidateStruct(valueField.Interface()); structErrors != nil { + if structErrors := v.validateStructRecursive(top, valueField.Interface()); structErrors != nil { validationErrors.StructErrors[typeField.Name] = structErrors // free up memory map no longer needed structErrors = nil From 622107d990ec24e8ced5fea6c2386c463fcf1e8e Mon Sep 17 00:00:00 2001 From: Dean Karn Date: Sat, 21 Mar 2015 13:35:17 -0400 Subject: [PATCH 2/2] issue-#18 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add “structonly” tag for struct only and not field validation --- doc.go | 7 +++++++ validator.go | 5 +++++ validator_test.go | 29 +++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/doc.go b/doc.go index 8abe6ab..e71e0d4 100644 --- a/doc.go +++ b/doc.go @@ -150,6 +150,13 @@ Here is a list of the current built in validators: colors to be accepted. This can also be combined with 'and' for example ( Usage: omitempty,rgb|rgba) + structonly + When a field that is a nest struct in encountered and contains this flag + any validation on the nested struct such as "required" will be run, but + none of the nested struct fields will be validated. This is usefull if + inside of you program you know the struct will be valid, but need to + verify it has been assigned. + omitempty Allows conitional validation, for example if a field is not set with a value (Determined by the required validator) then other validation diff --git a/validator.go b/validator.go index 9ba8e24..5f027ba 100644 --- a/validator.go +++ b/validator.go @@ -22,6 +22,7 @@ const ( orSeparator = "|" noValidationTag = "-" tagKeySeparator = "=" + structOnlyTag = "structonly" omitempty = "omitempty" validationFieldErrMsg = "Field validation for \"%s\" failed on the \"%s\" tag\n" validationStructErrMsg = "Struct:%s\n" @@ -216,6 +217,10 @@ func (v *Validator) validateStructRecursive(top interface{}, s interface{}) *Str } else { + if strings.Contains(tag, structOnlyTag) { + continue + } + if structErrors := v.validateStructRecursive(top, valueField.Interface()); structErrors != nil { validationErrors.StructErrors[typeField.Name] = structErrors // free up memory map no longer needed diff --git a/validator_test.go b/validator_test.go index 299e18c..1849690 100644 --- a/validator_test.go +++ b/validator_test.go @@ -137,6 +137,35 @@ func isEqualFunc(val interface{}, field interface{}, param string) bool { return val.(string) == field.(string) } +func (ms *MySuite) TestStructOnlyValidation(c *C) { + + type Inner struct { + Test string `validate:"len=5"` + } + + type Outer struct { + InnerStruct *Inner `validate:"required,structonly"` + } + + outer := &Outer{ + InnerStruct: nil, + } + + errs := myValidator.ValidateStruct(outer).Flatten() + c.Assert(errs, NotNil) + + inner := &Inner{ + Test: "1234", + } + + outer = &Outer{ + InnerStruct: inner, + } + + errs = myValidator.ValidateStruct(outer).Flatten() + c.Assert(errs, IsNil) +} + func (ms *MySuite) TestGtField(c *C) { type TimeTest struct {