From ddb9ed39a5ef697d1c9a2ce2879d8cbb431b37ee Mon Sep 17 00:00:00 2001 From: miraclesu Date: Mon, 22 Jul 2013 17:40:32 +0800 Subject: [PATCH 1/5] add validation README --- validation/README.md | 50 +++++++++++++++++++++++++++++++++++ validation/validation_test.go | 2 +- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 validation/README.md diff --git a/validation/README.md b/validation/README.md new file mode 100644 index 00000000..34036261 --- /dev/null +++ b/validation/README.md @@ -0,0 +1,50 @@ +validation +============== + +validation is a form validation for a data validation and error collecting using Go. + +## Installation and tests + +Install: + + go get github.com/astaxie/beego/validation + +Test: + + go test github.com/astaxie/beego/validation + +## Example + + import ( + "github.com/astaxie/beego/validation" + "log" + ) + + type User struct { + Name string + Age int + } + + func main() { + u := User{"man", 40} + valid := validation.Validation{} + valid.Required(u.Name, "name") + valid.MaxSize(u.Name, 15, "nameMax") + valid.Range(u.Age, 0, 140, "age") + if valid.HasErrors { + // validation does not pass + // print invalid message + for _, err := range valid.Errors { + log.Println(err.Key, err.Message) + } + } + // or use like this + if v := valid.Max(u.Age, 140); !v.Ok { + log.Println(v.Error.Key, v.Error.Message) + } + } + + +## LICENSE + +BSD License http://creativecommons.org/licenses/BSD/ diff --git a/validation/validation_test.go b/validation/validation_test.go index 9f814367..389fd78a 100644 --- a/validation/validation_test.go +++ b/validation/validation_test.go @@ -31,7 +31,7 @@ func TestRequired(t *testing.T) { t.Error("empty slice should be false") } if !valid.Required([]interface{}{"ok"}, "slice").Ok { - t.Error("slice should be equal true") + t.Error("slice should be true") } } From aba1728bc3e7500f5c83cac563254c821c56f1d2 Mon Sep 17 00:00:00 2001 From: miraclesu Date: Tue, 23 Jul 2013 14:42:14 +0800 Subject: [PATCH 2/5] add some util funcs --- validation/util.go | 131 ++++++++++++++++++++++++++++++++++++++++ validation/util_test.go | 58 ++++++++++++++++++ 2 files changed, 189 insertions(+) create mode 100644 validation/util.go create mode 100644 validation/util_test.go diff --git a/validation/util.go b/validation/util.go new file mode 100644 index 00000000..a2e30656 --- /dev/null +++ b/validation/util.go @@ -0,0 +1,131 @@ +package validation + +import ( + "fmt" + "reflect" + "strings" +) + +const ( + VALIDTAG = "valid" +) + +var ( + // key: function name + // value: the number of parameters + funcs = make(map[string]int) + + // doesn't belong to validation functions + unFuncs = map[string]bool{ + "Clear": true, + "HasErrors": true, + "ErrorMap": true, + "Error": true, + "apply": true, + "Check": true, + "Valid": true, + } +) + +func init() { + v := &Validation{} + t := reflect.TypeOf(v) + for i := 0; i < t.NumMethod(); i++ { + m := t.Method(i) + if !unFuncs[m.Name] { + funcs[m.Name] = m.Type.NumIn() - 3 + } + } +} + +type ValidFunc struct { + Name string + Params []interface{} +} + +func isStruct(t reflect.Type) bool { + return t.Kind() == reflect.Struct +} + +func isStructPtr(t reflect.Type) bool { + return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct +} + +func getValidFuncs(f reflect.StructField) (vfs []ValidFunc, err error) { + tag := f.Tag.Get(VALIDTAG) + if len(tag) == 0 { + return + } + fs := strings.Split(tag, ";") + for _, vfunc := range fs { + var vf ValidFunc + vf, err = parseFunc(vfunc) + if err != nil { + return + } + vfs = append(vfs, vf) + } + return +} + +func parseFunc(vfunc string) (v ValidFunc, err error) { + defer func() { + if r := recover(); r != nil { + err = r.(error) + } + }() + + vfunc = strings.TrimSpace(vfunc) + start := strings.Index(vfunc, "(") + var num int + + // doesn't need parameter valid function + if start == -1 { + if num, err = numIn(vfunc); err != nil { + return + } + if num != 0 { + err = fmt.Errorf("%s require %d parameters", vfunc, num) + return + } + v = ValidFunc{Name: vfunc} + return + } + + end := strings.Index(vfunc, ")") + if end == -1 { + err = fmt.Errorf("invalid valid function") + return + } + + name := strings.TrimSpace(vfunc[:start]) + if num, err = numIn(name); err != nil { + return + } + + params := strings.Split(vfunc[start+1:end], ",") + // the num of param must be equal + if num != len(params) { + err = fmt.Errorf("%s require %d parameters", name, num) + return + } + + v = ValidFunc{name, trim(params)} + return +} + +func numIn(name string) (num int, err error) { + num, ok := funcs[name] + if !ok { + err = fmt.Errorf("doesn't exsits %s valid function", name) + } + return +} + +func trim(s []string) []interface{} { + ts := make([]interface{}, len(s)) + for i := 0; i < len(s); i++ { + ts[i] = strings.TrimSpace(s[i]) + } + return ts +} diff --git a/validation/util_test.go b/validation/util_test.go new file mode 100644 index 00000000..e9fbf6a9 --- /dev/null +++ b/validation/util_test.go @@ -0,0 +1,58 @@ +package validation + +import ( + "reflect" + "testing" +) + +type user struct { + Id int + Tag string `valid:"Maxx(aa)"` + Name string `valid:"Required"` + Age int `valid:"Required;Range(1, 140)"` +} + +func TestGetValidFuncs(t *testing.T) { + u := user{Name: "test", Age: 1} + tf := reflect.TypeOf(u) + var vfs []ValidFunc + var err error + + f, _ := tf.FieldByName("Id") + if vfs, err = getValidFuncs(f); err != nil { + t.Fatal(err) + } + if len(vfs) != 0 { + t.Fatal("should get none ValidFunc") + } + + f, _ = tf.FieldByName("Tag") + if vfs, err = getValidFuncs(f); err.Error() != "doesn't exsits Maxx valid function" { + t.Fatal(err) + } + + f, _ = tf.FieldByName("Name") + if vfs, err = getValidFuncs(f); err != nil { + t.Fatal(err) + } + if len(vfs) != 1 { + t.Fatal("should get 1 ValidFunc") + } + if vfs[0].Name != "Required" && len(vfs[0].Params) != 0 { + t.Error("Required funcs should be got") + } + + f, _ = tf.FieldByName("Age") + if vfs, err = getValidFuncs(f); err != nil { + t.Fatal(err) + } + if len(vfs) != 2 { + t.Fatal("should get 2 ValidFunc") + } + if vfs[0].Name != "Required" && len(vfs[0].Params) != 0 { + t.Error("Required funcs should be got") + } + if vfs[1].Name != "Range" && len(vfs[1].Params) != 2 { + t.Error("Range funcs should be got") + } +} From 4c6163baa047091f9b809f131d777666916c1518 Mon Sep 17 00:00:00 2001 From: miraclesu Date: Wed, 24 Jul 2013 01:20:24 +0800 Subject: [PATCH 3/5] add funcmap --- validation/util.go | 70 ++++++++++++++++++++++++++++++----- validation/util_test.go | 16 ++++++++ validation/validation.go | 27 ++++++++++++++ validation/validation_test.go | 18 ++++----- validation/validators.go | 30 +++++++-------- 5 files changed, 128 insertions(+), 33 deletions(-) diff --git a/validation/util.go b/validation/util.go index a2e30656..3eeabab0 100644 --- a/validation/util.go +++ b/validation/util.go @@ -3,6 +3,8 @@ package validation import ( "fmt" "reflect" + "regexp" + "strconv" "strings" ) @@ -13,7 +15,7 @@ const ( var ( // key: function name // value: the number of parameters - funcs = make(map[string]int) + funcs = make(Funcs) // doesn't belong to validation functions unFuncs = map[string]bool{ @@ -33,7 +35,7 @@ func init() { for i := 0; i < t.NumMethod(); i++ { m := t.Method(i) if !unFuncs[m.Name] { - funcs[m.Name] = m.Type.NumIn() - 3 + funcs[m.Name] = m.Func } } } @@ -43,6 +45,25 @@ type ValidFunc struct { Params []interface{} } +type Funcs map[string]reflect.Value + +func (f Funcs) Call(name string, params ...interface{}) (result []reflect.Value, err error) { + if _, ok := f[name]; !ok { + err = fmt.Errorf("%s does not exist", name) + return + } + if len(params) != f[name].Type().NumIn() { + err = fmt.Errorf("The number of params is not adapted") + return + } + in := make([]reflect.Value, len(params)) + for k, param := range params { + in[k] = reflect.ValueOf(param) + } + result = f[name].Call(in) + return +} + func isStruct(t reflect.Type) bool { return t.Kind() == reflect.Struct } @@ -110,22 +131,53 @@ func parseFunc(vfunc string) (v ValidFunc, err error) { return } - v = ValidFunc{name, trim(params)} + tParams, err := trim(name, params) + if err != nil { + return + } + v = ValidFunc{name, tParams} return } func numIn(name string) (num int, err error) { - num, ok := funcs[name] + fn, ok := funcs[name] if !ok { err = fmt.Errorf("doesn't exsits %s valid function", name) + return + } + num = fn.Type().NumIn() - 3 + return +} + +func trim(name string, s []string) (ts []interface{}, err error) { + ts = make([]interface{}, len(s)) + fn, ok := funcs[name] + if !ok { + err = fmt.Errorf("doesn't exsits %s valid function", name) + return + } + for i := 0; i < len(s); i++ { + var param interface{} + if param, err = magic(fn.Type().In(i+2), strings.TrimSpace(s[i])); err != nil { + return + } + ts[i] = param } return } -func trim(s []string) []interface{} { - ts := make([]interface{}, len(s)) - for i := 0; i < len(s); i++ { - ts[i] = strings.TrimSpace(s[i]) +func magic(t reflect.Type, s string) (i interface{}, err error) { + switch t.Kind() { + case reflect.Int: + i, err = strconv.Atoi(s) + case reflect.String: + i = s + case reflect.Ptr: + if t.Elem().String() != "regexp.Regexp" { + err = fmt.Errorf("%s does not support", t.Elem().String()) + return + } + i, err = regexp.Compile(s) } - return ts + return } diff --git a/validation/util_test.go b/validation/util_test.go index e9fbf6a9..a76a81a8 100644 --- a/validation/util_test.go +++ b/validation/util_test.go @@ -56,3 +56,19 @@ func TestGetValidFuncs(t *testing.T) { t.Error("Range funcs should be got") } } + +func TestCall(t *testing.T) { + u := user{Name: "test", Age: 180} + tf := reflect.TypeOf(u) + var vfs []ValidFunc + var err error + f, _ := tf.FieldByName("Age") + if vfs, err = getValidFuncs(f); err != nil { + t.Fatal(err) + } + valid := &Validation{} + funcs.Call(vfs[1].Name, valid, u.Age, vfs[1].Params[0], vfs[1].Params[1], vfs[1].Name) + if len(valid.Errors) != 1 { + t.Error("age out of range should be has an error") + } +} diff --git a/validation/validation.go b/validation/validation.go index fa2c7bc3..af5df744 100644 --- a/validation/validation.go +++ b/validation/validation.go @@ -2,6 +2,7 @@ package validation import ( "fmt" + "reflect" "regexp" ) @@ -175,3 +176,29 @@ func (v *Validation) Check(obj interface{}, checks ...Validator) *ValidationResu } return result } + +// the obj parameter must be a struct or a struct pointer +func (v *Validation) Valid(obj interface{}) (b bool, err error) { + t := reflect.TypeOf(obj) + switch { + case isStruct(t): + case isStructPtr(t): + t = t.Elem() + default: + err = fmt.Errorf("%v must be a struct or a struct pointer", obj) + return + } + // tv := reflect.TypeOf(v) + // for i := 0; i < t.NumField(); i++ { + // f := t.Field(i) + // var vfs []ValidFunc + // if vfs, err = getValidFuncs(f); err != nil { + // return + // } + // for _, vf := range vfs { + // m, _ := tv.MethodByName(vf.Name) + // m.Func + // } + // } + return +} diff --git a/validation/validation_test.go b/validation/validation_test.go index 389fd78a..1d6b18dd 100644 --- a/validation/validation_test.go +++ b/validation/validation_test.go @@ -57,16 +57,16 @@ func TestMax(t *testing.T) { } } -func TestRange(t *testing.T) { - valid := Validation{} +// func TestRange(t *testing.T) { +// valid := Validation{} - if valid.Range(-1, 0, 1, "range0_1").Ok { - t.Error("-1 is bettween 0 and 1 should be false") - } - if !valid.Range(1, 0, 1, "range0_1").Ok { - t.Error("1 is bettween 0 and 1 should be true") - } -} +// if valid.Range(-1, 0, 1, "range0_1").Ok { +// t.Error("-1 is bettween 0 and 1 should be false") +// } +// if !valid.Range(1, 0, 1, "range0_1").Ok { +// t.Error("1 is bettween 0 and 1 should be true") +// } +// } func TestMinSize(t *testing.T) { valid := Validation{} diff --git a/validation/validators.go b/validation/validators.go index 41ed02ed..e8533749 100644 --- a/validation/validators.go +++ b/validation/validators.go @@ -63,7 +63,7 @@ func (m Min) IsSatisfied(obj interface{}) bool { } func (m Min) DefaultMessage() string { - return fmt.Sprintln("Minimum is", m.Min) + return fmt.Sprint("Minimum is ", m.Min) } func (m Min) GetKey() string { @@ -84,7 +84,7 @@ func (m Max) IsSatisfied(obj interface{}) bool { } func (m Max) DefaultMessage() string { - return fmt.Sprintln("Maximum is", m.Max) + return fmt.Sprint("Maximum is ", m.Max) } func (m Max) GetKey() string { @@ -103,7 +103,7 @@ func (r Range) IsSatisfied(obj interface{}) bool { } func (r Range) DefaultMessage() string { - return fmt.Sprintln("Range is", r.Min.Min, "to", r.Max.Max) + return fmt.Sprint("Range is ", r.Min.Min, " to ", r.Max.Max) } func (r Range) GetKey() string { @@ -128,7 +128,7 @@ func (m MinSize) IsSatisfied(obj interface{}) bool { } func (m MinSize) DefaultMessage() string { - return fmt.Sprintln("Minimum size is", m.Min) + return fmt.Sprint("Minimum size is ", m.Min) } func (m MinSize) GetKey() string { @@ -153,7 +153,7 @@ func (m MaxSize) IsSatisfied(obj interface{}) bool { } func (m MaxSize) DefaultMessage() string { - return fmt.Sprintln("Maximum size is", m.Max) + return fmt.Sprint("Maximum size is ", m.Max) } func (m MaxSize) GetKey() string { @@ -178,7 +178,7 @@ func (l Length) IsSatisfied(obj interface{}) bool { } func (l Length) DefaultMessage() string { - return fmt.Sprintln("Required length is", l.N) + return fmt.Sprint("Required length is ", l.N) } func (l Length) GetKey() string { @@ -202,7 +202,7 @@ func (a Alpha) IsSatisfied(obj interface{}) bool { } func (a Alpha) DefaultMessage() string { - return fmt.Sprintln("Must be valid alpha characters") + return fmt.Sprint("Must be valid alpha characters") } func (a Alpha) GetKey() string { @@ -226,7 +226,7 @@ func (n Numeric) IsSatisfied(obj interface{}) bool { } func (n Numeric) DefaultMessage() string { - return fmt.Sprintln("Must be valid numeric characters") + return fmt.Sprint("Must be valid numeric characters") } func (n Numeric) GetKey() string { @@ -250,7 +250,7 @@ func (a AlphaNumeric) IsSatisfied(obj interface{}) bool { } func (a AlphaNumeric) DefaultMessage() string { - return fmt.Sprintln("Must be valid alpha or numeric characters") + return fmt.Sprint("Must be valid alpha or numeric characters") } func (a AlphaNumeric) GetKey() string { @@ -269,7 +269,7 @@ func (m Match) IsSatisfied(obj interface{}) bool { } func (m Match) DefaultMessage() string { - return fmt.Sprintln("Must match", m.Regexp) + return fmt.Sprint("Must match ", m.Regexp) } func (m Match) GetKey() string { @@ -287,7 +287,7 @@ func (n NoMatch) IsSatisfied(obj interface{}) bool { } func (n NoMatch) DefaultMessage() string { - return fmt.Sprintln("Must not match", n.Regexp) + return fmt.Sprint("Must not match ", n.Regexp) } func (n NoMatch) GetKey() string { @@ -302,7 +302,7 @@ type AlphaDash struct { } func (a AlphaDash) DefaultMessage() string { - return fmt.Sprintln("Must be valid alpha or numeric or dash(-_) characters") + return fmt.Sprint("Must be valid alpha or numeric or dash(-_) characters") } func (a AlphaDash) GetKey() string { @@ -317,7 +317,7 @@ type Email struct { } func (e Email) DefaultMessage() string { - return fmt.Sprintln("Must be a valid email address") + return fmt.Sprint("Must be a valid email address") } func (e Email) GetKey() string { @@ -332,7 +332,7 @@ type IP struct { } func (i IP) DefaultMessage() string { - return fmt.Sprintln("Must be a valid ip address") + return fmt.Sprint("Must be a valid ip address") } func (i IP) GetKey() string { @@ -347,7 +347,7 @@ type Base64 struct { } func (b Base64) DefaultMessage() string { - return fmt.Sprintln("Must be valid base64 characters") + return fmt.Sprint("Must be valid base64 characters") } func (b Base64) GetKey() string { From 92db56c0cb8312cffdeff3202d89700b073cc6e4 Mon Sep 17 00:00:00 2001 From: miraclesu Date: Wed, 24 Jul 2013 12:20:42 +0800 Subject: [PATCH 4/5] add struct tag support --- validation/util.go | 21 +++++++++++++--- validation/util_test.go | 5 +++- validation/validation.go | 37 +++++++++++++++------------- validation/validation_test.go | 45 ++++++++++++++++++++++++++++------- 4 files changed, 78 insertions(+), 30 deletions(-) diff --git a/validation/util.go b/validation/util.go index 3eeabab0..cbdb1fa3 100644 --- a/validation/util.go +++ b/validation/util.go @@ -48,6 +48,11 @@ type ValidFunc struct { type Funcs map[string]reflect.Value 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 { err = fmt.Errorf("%s does not exist", name) return @@ -109,7 +114,7 @@ func parseFunc(vfunc string) (v ValidFunc, err error) { err = fmt.Errorf("%s require %d parameters", vfunc, num) return } - v = ValidFunc{Name: vfunc} + v = ValidFunc{vfunc, []interface{}{vfunc}} return } @@ -145,12 +150,13 @@ func numIn(name string) (num int, err error) { err = fmt.Errorf("doesn't exsits %s valid function", name) return } + // sub *Validation obj and key num = fn.Type().NumIn() - 3 return } 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] if !ok { 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++ { var param interface{} + // skip *Validation and obj params if param, err = magic(fn.Type().In(i+2), strings.TrimSpace(s[i])); err != nil { return } ts[i] = param } + ts = append(ts, name) return } +// modify the parameters's type to adapt the function input parameters' type func magic(t reflect.Type, s string) (i interface{}, err error) { switch t.Kind() { case reflect.Int: @@ -174,10 +183,16 @@ func magic(t reflect.Type, s string) (i interface{}, err error) { i = s case reflect.Ptr: 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 } i, err = regexp.Compile(s) + default: + err = fmt.Errorf("does not support %s", t.Kind().String()) } return } + +func mergeParam(v *Validation, obj interface{}, params []interface{}) []interface{} { + return append([]interface{}{v, obj}, params...) +} diff --git a/validation/util_test.go b/validation/util_test.go index a76a81a8..e181871f 100644 --- a/validation/util_test.go +++ b/validation/util_test.go @@ -67,7 +67,10 @@ func TestCall(t *testing.T) { t.Fatal(err) } 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 { t.Error("age out of range should be has an error") } diff --git a/validation/validation.go b/validation/validation.go index af5df744..46251716 100644 --- a/validation/validation.go +++ b/validation/validation.go @@ -179,26 +179,29 @@ func (v *Validation) Check(obj interface{}, checks ...Validator) *ValidationResu // the obj parameter must be a struct or a struct pointer func (v *Validation) Valid(obj interface{}) (b bool, err error) { - t := reflect.TypeOf(obj) + objT := reflect.TypeOf(obj) + objV := reflect.ValueOf(obj) switch { - case isStruct(t): - case isStructPtr(t): - t = t.Elem() + case isStruct(objT): + case isStructPtr(objT): + objT = objT.Elem() + objV = objV.Elem() default: err = fmt.Errorf("%v must be a struct or a struct pointer", obj) return } - // tv := reflect.TypeOf(v) - // for i := 0; i < t.NumField(); i++ { - // f := t.Field(i) - // var vfs []ValidFunc - // if vfs, err = getValidFuncs(f); err != nil { - // return - // } - // for _, vf := range vfs { - // m, _ := tv.MethodByName(vf.Name) - // m.Func - // } - // } - return + + for i := 0; i < objT.NumField(); i++ { + var vfs []ValidFunc + if vfs, err = getValidFuncs(objT.Field(i)); err != nil { + 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 } diff --git a/validation/validation_test.go b/validation/validation_test.go index 1d6b18dd..d9f35922 100644 --- a/validation/validation_test.go +++ b/validation/validation_test.go @@ -57,16 +57,16 @@ func TestMax(t *testing.T) { } } -// func TestRange(t *testing.T) { -// valid := Validation{} +func TestRange(t *testing.T) { + valid := Validation{} -// if valid.Range(-1, 0, 1, "range0_1").Ok { -// t.Error("-1 is bettween 0 and 1 should be false") -// } -// if !valid.Range(1, 0, 1, "range0_1").Ok { -// t.Error("1 is bettween 0 and 1 should be true") -// } -// } + if valid.Range(-1, 0, 1, "range0_1").Ok { + t.Error("-1 is bettween 0 and 1 should be false") + } + if !valid.Range(1, 0, 1, "range0_1").Ok { + t.Error("1 is bettween 0 and 1 should be true") + } +} func TestMinSize(t *testing.T) { valid := Validation{} @@ -217,3 +217,30 @@ func TestBase64(t *testing.T) { 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") + } +} From d23700b91926606b83d3b8bfe8a538c400bd47ae Mon Sep 17 00:00:00 2001 From: miraclesu Date: Wed, 24 Jul 2013 12:36:46 +0800 Subject: [PATCH 5/5] update README --- validation/README.md | 49 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/validation/README.md b/validation/README.md index 34036261..9d252799 100644 --- a/validation/README.md +++ b/validation/README.md @@ -15,6 +15,8 @@ Test: ## Example +Direct Use: + import ( "github.com/astaxie/beego/validation" "log" @@ -44,6 +46,53 @@ Test: } } +Struct Tag Use: + + import ( + "github.com/astaxie/beego/validation" + ) + + // validation function follow with "valid" tag + // functions divide with ";" + // parameters in parentheses "()" and divide with "," + type user struct { + Id int + Name string `valid:"Required"` + Age int `valid:"Required;Range(1, 140)"` + } + + func main() { + valid := Validation{} + u := user{Name: "test", Age: 40} + b, err := valid.Valid(u) + if err != nil { + // handle error + } + if !b { + // validation does not pass + // blabla... + } + } + +Struct Tag Functions: + + Required + Min(min int) + Max(max int) + Range(min, max int) + MinSize(min int) + MaxSize(max int) + Length(length int) + Alpha + Numeric + AlphaNumeric + Match(regexp string) // does not support yet + NoMatch(regexp string) // does not support yet + AlphaDash + Email + IP + Base64 + ## LICENSE