mirror of
https://github.com/astaxie/beego.git
synced 2024-11-22 19:30:55 +00:00
add struct tag support
This commit is contained in:
parent
4c6163baa0
commit
92db56c0cb
@ -48,6 +48,11 @@ type ValidFunc struct {
|
|||||||
type Funcs map[string]reflect.Value
|
type Funcs map[string]reflect.Value
|
||||||
|
|
||||||
func (f Funcs) Call(name string, params ...interface{}) (result []reflect.Value, err error) {
|
func (f Funcs) Call(name string, params ...interface{}) (result []reflect.Value, err error) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
err = r.(error)
|
||||||
|
}
|
||||||
|
}()
|
||||||
if _, ok := f[name]; !ok {
|
if _, ok := f[name]; !ok {
|
||||||
err = fmt.Errorf("%s does not exist", name)
|
err = fmt.Errorf("%s does not exist", name)
|
||||||
return
|
return
|
||||||
@ -109,7 +114,7 @@ func parseFunc(vfunc string) (v ValidFunc, err error) {
|
|||||||
err = fmt.Errorf("%s require %d parameters", vfunc, num)
|
err = fmt.Errorf("%s require %d parameters", vfunc, num)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
v = ValidFunc{Name: vfunc}
|
v = ValidFunc{vfunc, []interface{}{vfunc}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,12 +150,13 @@ func numIn(name string) (num int, err error) {
|
|||||||
err = fmt.Errorf("doesn't exsits %s valid function", name)
|
err = fmt.Errorf("doesn't exsits %s valid function", name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// sub *Validation obj and key
|
||||||
num = fn.Type().NumIn() - 3
|
num = fn.Type().NumIn() - 3
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func trim(name string, s []string) (ts []interface{}, err error) {
|
func trim(name string, s []string) (ts []interface{}, err error) {
|
||||||
ts = make([]interface{}, len(s))
|
ts = make([]interface{}, len(s), len(s)+1)
|
||||||
fn, ok := funcs[name]
|
fn, ok := funcs[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
err = fmt.Errorf("doesn't exsits %s valid function", name)
|
err = fmt.Errorf("doesn't exsits %s valid function", name)
|
||||||
@ -158,14 +164,17 @@ func trim(name string, s []string) (ts []interface{}, err error) {
|
|||||||
}
|
}
|
||||||
for i := 0; i < len(s); i++ {
|
for i := 0; i < len(s); i++ {
|
||||||
var param interface{}
|
var param interface{}
|
||||||
|
// skip *Validation and obj params
|
||||||
if param, err = magic(fn.Type().In(i+2), strings.TrimSpace(s[i])); err != nil {
|
if param, err = magic(fn.Type().In(i+2), strings.TrimSpace(s[i])); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ts[i] = param
|
ts[i] = param
|
||||||
}
|
}
|
||||||
|
ts = append(ts, name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// modify the parameters's type to adapt the function input parameters' type
|
||||||
func magic(t reflect.Type, s string) (i interface{}, err error) {
|
func magic(t reflect.Type, s string) (i interface{}, err error) {
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
case reflect.Int:
|
case reflect.Int:
|
||||||
@ -174,10 +183,16 @@ func magic(t reflect.Type, s string) (i interface{}, err error) {
|
|||||||
i = s
|
i = s
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
if t.Elem().String() != "regexp.Regexp" {
|
if t.Elem().String() != "regexp.Regexp" {
|
||||||
err = fmt.Errorf("%s does not support", t.Elem().String())
|
err = fmt.Errorf("does not support %s", t.Elem().String())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
i, err = regexp.Compile(s)
|
i, err = regexp.Compile(s)
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("does not support %s", t.Kind().String())
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mergeParam(v *Validation, obj interface{}, params []interface{}) []interface{} {
|
||||||
|
return append([]interface{}{v, obj}, params...)
|
||||||
|
}
|
||||||
|
@ -67,7 +67,10 @@ func TestCall(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
valid := &Validation{}
|
valid := &Validation{}
|
||||||
funcs.Call(vfs[1].Name, valid, u.Age, vfs[1].Params[0], vfs[1].Params[1], vfs[1].Name)
|
vfs[1].Params = append([]interface{}{valid, u.Age}, vfs[1].Params...)
|
||||||
|
if _, err = funcs.Call(vfs[1].Name, vfs[1].Params...); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
if len(valid.Errors) != 1 {
|
if len(valid.Errors) != 1 {
|
||||||
t.Error("age out of range should be has an error")
|
t.Error("age out of range should be has an error")
|
||||||
}
|
}
|
||||||
|
@ -179,26 +179,29 @@ func (v *Validation) Check(obj interface{}, checks ...Validator) *ValidationResu
|
|||||||
|
|
||||||
// the obj parameter must be a struct or a struct pointer
|
// the obj parameter must be a struct or a struct pointer
|
||||||
func (v *Validation) Valid(obj interface{}) (b bool, err error) {
|
func (v *Validation) Valid(obj interface{}) (b bool, err error) {
|
||||||
t := reflect.TypeOf(obj)
|
objT := reflect.TypeOf(obj)
|
||||||
|
objV := reflect.ValueOf(obj)
|
||||||
switch {
|
switch {
|
||||||
case isStruct(t):
|
case isStruct(objT):
|
||||||
case isStructPtr(t):
|
case isStructPtr(objT):
|
||||||
t = t.Elem()
|
objT = objT.Elem()
|
||||||
|
objV = objV.Elem()
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("%v must be a struct or a struct pointer", obj)
|
err = fmt.Errorf("%v must be a struct or a struct pointer", obj)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// tv := reflect.TypeOf(v)
|
|
||||||
// for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < objT.NumField(); i++ {
|
||||||
// f := t.Field(i)
|
var vfs []ValidFunc
|
||||||
// var vfs []ValidFunc
|
if vfs, err = getValidFuncs(objT.Field(i)); err != nil {
|
||||||
// if vfs, err = getValidFuncs(f); err != nil {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// for _, vf := range vfs {
|
|
||||||
// m, _ := tv.MethodByName(vf.Name)
|
|
||||||
// m.Func
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
for _, vf := range vfs {
|
||||||
|
if _, err = funcs.Call(vf.Name,
|
||||||
|
mergeParam(v, objV.Field(i).Interface(), vf.Params)...); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !v.HasErrors(), nil
|
||||||
}
|
}
|
||||||
|
@ -57,16 +57,16 @@ func TestMax(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// func TestRange(t *testing.T) {
|
func TestRange(t *testing.T) {
|
||||||
// valid := Validation{}
|
valid := Validation{}
|
||||||
|
|
||||||
// if valid.Range(-1, 0, 1, "range0_1").Ok {
|
if valid.Range(-1, 0, 1, "range0_1").Ok {
|
||||||
// t.Error("-1 is bettween 0 and 1 should be false")
|
t.Error("-1 is bettween 0 and 1 should be false")
|
||||||
// }
|
}
|
||||||
// if !valid.Range(1, 0, 1, "range0_1").Ok {
|
if !valid.Range(1, 0, 1, "range0_1").Ok {
|
||||||
// t.Error("1 is bettween 0 and 1 should be true")
|
t.Error("1 is bettween 0 and 1 should be true")
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
func TestMinSize(t *testing.T) {
|
func TestMinSize(t *testing.T) {
|
||||||
valid := Validation{}
|
valid := Validation{}
|
||||||
@ -217,3 +217,30 @@ func TestBase64(t *testing.T) {
|
|||||||
t.Error("\"c3VjaHVhbmdqaUBnbWFpbC5jb20=\" are a valid base64 characters should be true")
|
t.Error("\"c3VjaHVhbmdqaUBnbWFpbC5jb20=\" are a valid base64 characters should be true")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValid(t *testing.T) {
|
||||||
|
type user struct {
|
||||||
|
Id int
|
||||||
|
Name string `valid:"Required"`
|
||||||
|
Age int `valid:"Required;Range(1, 140)"`
|
||||||
|
}
|
||||||
|
valid := Validation{}
|
||||||
|
|
||||||
|
u := user{Name: "test", Age: 40}
|
||||||
|
b, err := valid.Valid(u)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !b {
|
||||||
|
t.Error("validation should be passed")
|
||||||
|
}
|
||||||
|
|
||||||
|
uptr := &user{Name: "test", Age: 180}
|
||||||
|
b, err = valid.Valid(uptr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if b {
|
||||||
|
t.Error("validation should not be passed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user