Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support exp variable for bind and validator #74

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions binding/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ func (b *Binding) BindAndValidate(recvPointer interface{}, req *http.Request, pa
return b.IBindAndValidate(recvPointer, wrapRequest(req), pathParams)
}

// BindAndValidateWithEnv binds the request parameters and validates them if needed.
func (b *Binding) BindAndValidateWithEnv(recvPointer interface{}, req *http.Request, pathParams PathParams, env map[string]interface{}) error {
return b.IBindAndValidateWithEnv(recvPointer, wrapRequest(req), pathParams, env)
}

// Bind binds the request parameters.
func (b *Binding) Bind(recvPointer interface{}, req *http.Request, pathParams PathParams) error {
return b.IBind(recvPointer, wrapRequest(req), pathParams)
Expand All @@ -102,11 +107,30 @@ func (b *Binding) IBind(recvPointer interface{}, req Request, pathParams PathPar
return err
}

// IBindAndValidateWithEnv binds the request parameters and validates them if needed.
func (b *Binding) IBindAndValidateWithEnv(recvPointer interface{}, req Request, pathParams PathParams, env map[string]interface{}) error {
v, hasVd, err := b.bind(recvPointer, req, pathParams)
if err != nil {
return err
}
if hasVd {
return b.vd.ValidateWithEnv(v, env)
}
return nil
}


// Validate validates whether the fields of value is valid.
func (b *Binding) Validate(value interface{}) error {
return b.vd.Validate(value)
}

// ValidateWithEnv validates whether the fields of value is valid.
func (b *Binding) ValidateWithEnv(value interface{}, env map[string]interface{}) error {
return b.vd.ValidateWithEnv(value, env)
}


func (b *Binding) bind(pointer interface{}, req Request, pathParams PathParams) (elemValue reflect.Value, hasVd bool, err error) {
elemValue, err = b.receiverValueOf(pointer)
if err != nil {
Expand Down
11 changes: 11 additions & 0 deletions binding/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,14 @@ func Bind(structPointer interface{}, req *http.Request, pathParams PathParams) e
func Validate(value interface{}) error {
return defaultBinding.Validate(value)
}


// BindAndValidateWithEnv binds the request parameters and validates them if needed.
func BindAndValidateWithEnv(structPointer interface{}, req *http.Request, pathParams PathParams, env map[string]interface{}) error {
return defaultBinding.BindAndValidateWithEnv(structPointer, req, pathParams, env)
}

// ValidateWithEnv validates whether the fields of value is valid.
func ValidateWithEnv(value interface{}, env map[string]interface{}) error {
return defaultBinding.ValidateWithEnv(value, env)
}
7 changes: 7 additions & 0 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,10 @@ func (e *ExprHandler) EvalString() string {
func (e *ExprHandler) EvalBool() bool {
return FakeBool(e.Eval())
}

// EvalWithEnv evaluate the value of the struct tag expression.
// NOTE:
// result types: float64, string, bool, nil
func (e *ExprHandler) EvalWithEnv(env map[string]interface{}) interface{} {
return e.expr.s.exprs[e.selector].runWithEnv(e.base, e.targetExpr, env)
}
9 changes: 9 additions & 0 deletions tagexpr.go
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,15 @@ func (t *TagExpr) EvalString(exprSelector string) string {
return r
}

// EvalStringWithEnv evaluates the value of the struct tag expression by the selector expression.
// NOTE:
//
// If the expression value type is not string, return "".
func (t *TagExpr) EvalStringWithEnv(exprSelector string, env map[string]interface{}) string {
r, _ := t.EvalWithEnv(exprSelector, env).(string)
return r
}

// EvalBool evaluates the value of the struct tag expression by the selector expression.
// NOTE:
//
Expand Down
1 change: 1 addition & 0 deletions validator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ A powerful validator that supports struct tag expression.
- Support access to any field in the current structure
- Support access to nested fields, non-exported fields, etc.
- Support registers validator function expression
- Support variable
- Built-in len, sprintf, regexp, email, phone functions
- Support simple mode, or specify error message mode
- Use offset pointers to directly take values, better performance
Expand Down
9 changes: 9 additions & 0 deletions validator/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ func Validate(value interface{}, checkAll ...bool) error {
return defaultValidator.Validate(value, checkAll...)
}

// ValidateWithEnv uses the default validator to validate whether the fields of value is valid.
// NOTE:
// The tag name is 'vd'
// If checkAll=true, validate all the error.
func ValidateWithEnv(value interface{}, env map[string]interface{}, checkAll ...bool) error {
return defaultValidator.ValidateWithEnv(value, env, checkAll...)
}


// SetErrorFactory customizes the factory of validation error for the default validator.
// NOTE:
// The tag name is 'vd'
Expand Down
14 changes: 14 additions & 0 deletions validator/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ func Example() {
}
f := &F{}
f.f.g = 10

type G struct {
intValue int `vd:"$>minVal"`
}

g := &G{
intValue: 10,
}

fmt.Println(vd.Validate(f))

fmt.Println(vd.Validate(map[string]*F{"a": f}))
Expand All @@ -85,6 +94,9 @@ func Example() {
fmt.Println(vd.Validate(map[string]map[string]*F{}))
fmt.Println(vd.Validate([]map[string]*F{}))
fmt.Println(vd.Validate([]*F{}))
fmt.Println(vd.ValidateWithEnv(g, map[string]interface{}{"minVal": 9}))
fmt.Println(vd.ValidateWithEnv(g, map[string]interface{}{"minVal": 11}))


// Output:
// <nil>
Expand All @@ -105,4 +117,6 @@ func Example() {
// <nil>
// <nil>
// <nil>
// <nil>
// {"succ":false, "error":"validation failed: intValue"}
}
11 changes: 9 additions & 2 deletions validator/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ func (v *Validator) VM() *tagexpr.VM {
// NOTE:
// If checkAll=true, validate all the error.
func (v *Validator) Validate(value interface{}, checkAll ...bool) error {
return v.ValidateWithEnv(value, nil, checkAll...)
}

// Validate validates whether the fields of value is valid.
// NOTE:
// If checkAll=true, validate all the error.
func (v *Validator) ValidateWithEnv(value interface{}, env map[string]interface{},checkAll ...bool) error {
var all bool
if len(checkAll) > 0 {
all = checkAll[0]
Expand All @@ -75,7 +82,7 @@ func (v *Validator) Validate(value interface{}, checkAll ...bool) error {
if strings.Contains(eh.StringSelector(), tagexpr.ExprNameSeparator) {
return nil
}
r := eh.Eval()
r := eh.EvalWithEnv(env)
if r == nil {
return nil
}
Expand All @@ -96,7 +103,7 @@ func (v *Validator) Validate(value interface{}, checkAll ...bool) error {
}
}
}
msg := eh.TagExpr().EvalString(eh.StringSelector() + tagexpr.ExprNameSeparator + ErrMsgExprName)
msg := eh.TagExpr().EvalStringWithEnv(eh.StringSelector() + tagexpr.ExprNameSeparator + ErrMsgExprName,env)
if msg == "" && rerr != nil {
msg = rerr.Error()
}
Expand Down
Loading