42556305 by Wyatt Fang Committed by astaxie

add Recursively validation

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