commit
						1e1068e81c
					
				| @ -334,3 +334,41 @@ func (v *Validation) Valid(obj interface{}) (b bool, err error) { | |||||||
| 
 | 
 | ||||||
| 	return !v.HasErrors(), nil | 	return !v.HasErrors(), nil | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // Recursively validate a struct. | ||||||
|  | // Step1: Validate by v.Valid | ||||||
|  | // Step2: If pass on step1, then reflect obj's fields | ||||||
|  | // Step3: Do the Recursively validation to all struct or struct pointer fields | ||||||
|  | func (v *Validation) RecursiveValid(objc interface{}) (bool, error) { | ||||||
|  | 	//Step 1: validate obj itself firstly | ||||||
|  | 	// fails if objc is not struct | ||||||
|  | 	pass, err := v.Valid(objc) | ||||||
|  | 	if err != nil || false == pass { | ||||||
|  | 		return pass, err // Stop recursive validation | ||||||
|  | 	} else { //pass | ||||||
|  | 		// Step 2: Validate struct's struct fields | ||||||
|  | 		objT := reflect.TypeOf(objc) | ||||||
|  | 		objV := reflect.ValueOf(objc) | ||||||
|  | 
 | ||||||
|  | 		if isStructPtr(objT) { | ||||||
|  | 			objT = objT.Elem() | ||||||
|  | 			objV = objV.Elem() | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for i := 0; i < objT.NumField(); i++ { | ||||||
|  | 
 | ||||||
|  | 			t := objT.Field(i).Type | ||||||
|  | 
 | ||||||
|  | 			// Recursive applies to struct or pointer to structs fields | ||||||
|  | 			if isStruct(t) || isStructPtr(t) { | ||||||
|  | 				// Step 3: do the recursive validation | ||||||
|  | 				// Only valid the Public field recursively | ||||||
|  | 				if objV.Field(i).CanInterface() { | ||||||
|  | 					pass, err = v.RecursiveValid(objV.Field(i).Interface()) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return pass, err | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
| @ -349,3 +349,33 @@ func TestValid(t *testing.T) { | |||||||
| 		t.Errorf("Message key should be `Name.Match` but got %s", valid.Errors[0].Key) | 		t.Errorf("Message key should be `Name.Match` but got %s", valid.Errors[0].Key) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func TestRecursiveValid(t *testing.T) { | ||||||
|  | 	type User struct { | ||||||
|  | 		Id   int | ||||||
|  | 		Name string `valid:"Required;Match(/^(test)?\\w*@(/test/);com$/)"` | ||||||
|  | 		Age  int    `valid:"Required;Range(1, 140)"` | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	type AnonymouseUser struct { | ||||||
|  | 		Id2   int | ||||||
|  | 		Name2 string `valid:"Required;Match(/^(test)?\\w*@(/test/);com$/)"` | ||||||
|  | 		Age2  int    `valid:"Required;Range(1, 140)"` | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	type Account struct { | ||||||
|  | 		Password string `valid:"Required"` | ||||||
|  | 		U        User | ||||||
|  | 		AnonymouseUser | ||||||
|  | 	} | ||||||
|  | 	valid := Validation{} | ||||||
|  | 
 | ||||||
|  | 	u := Account{Password: "abc123_", U: User{}} | ||||||
|  | 	b, err := valid.RecursiveValid(u) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	if b { | ||||||
|  | 		t.Error("validation should not be passed") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user