d0e7dd68 by Wyatt Fang

add Recursively validation

1 parent c4aa33fb
...@@ -333,3 +333,42 @@ func (v *Validation) Valid(obj interface{}) (b bool, err error) { ...@@ -333,3 +333,42 @@ func (v *Validation) Valid(obj interface{}) (b bool, err error) {
333 333
334 return !v.HasErrors(), nil 334 return !v.HasErrors(), nil
335 } 335 }
336
337 // Recursively validate a struct.
338 // Step1: Validate by v.Valid
339 // Step2: If pass on step1, then reflect obj's fields
340 // Step3: Do the Recursively validation to all struct or struct pointer fields
341 // Anonymous fields will be ignored
342 func (v *Validation) RecursiveValid(objc interface{}) (bool, error) {
343 //Step 1: validate obj itself firstly
344 pass, err := v.Valid(objc)
345 if err != nil || false == pass {
346 return pass, err // Stop recursive validation
347 } else { //pass
348 // Step 2: Validate struct's struct fields
349 objT := reflect.TypeOf(objc)
350 objV := reflect.ValueOf(objc)
351 if isStruct(objT) || isStructPtr(objT) {
352
353 if isStructPtr(objT) {
354 objT = objT.Elem()
355 objV = objV.Elem()
356 }
357
358 for i := 0; i < objT.NumField(); i++ {
359
360 t := objT.Field(i).Type
361
362 if isStruct(t) || isStructPtr(t) {
363 // Step 3: do the recursive validation
364 // Only valid the Public field recursively
365 if objV.Field(i).CanInterface() {
366 pass, err = v.RecursiveValid(objV.Field(i).Interface())
367 }
368 }
369 }
370 }
371
372 return pass, err
373 }
374 }
......
...@@ -343,3 +343,33 @@ func TestValid(t *testing.T) { ...@@ -343,3 +343,33 @@ func TestValid(t *testing.T) {
343 t.Errorf("Message key should be `Name.Match` but got %s", valid.Errors[0].Key) 343 t.Errorf("Message key should be `Name.Match` but got %s", valid.Errors[0].Key)
344 } 344 }
345 } 345 }
346
347 func TestRecursiveValid(t *testing.T) {
348 type User struct {
349 Id int
350 Name string `valid:"Required;Match(/^(test)?\\w*@(/test/);com$/)"`
351 Age int `valid:"Required;Range(1, 140)"`
352 }
353
354 type AnonymouseUser struct {
355 Id2 int
356 Name2 string `valid:"Required;Match(/^(test)?\\w*@(/test/);com$/)"`
357 Age2 int `valid:"Required;Range(1, 140)"`
358 }
359
360 type Account struct {
361 Password string `valid:"Required"`
362 U User
363 AnonymouseUser
364 }
365 valid := Validation{}
366
367 u := Account{Password: "abc123_", U: User{}}
368 b, err := valid.RecursiveValid(u)
369 if err != nil {
370 t.Fatal(err)
371 }
372 if b {
373 t.Error("validation should not be passed")
374 }
375 }
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!