# README

validator GoDoc

A powerful validator that supports struct tag expression.

Feature

  • Support for a variety of common operator
  • Support for accessing arrays, slices, members of the dictionary
  • Support access to any field in the current structure
  • Support access to nested fields, non-exported fields, etc.
  • Support registers validator function expression
  • 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
  • Required go version ≥1.9

Example

package validator_test

import (
	"fmt"

	vd "github.com/bytedance/go-tagexpr/validator"
)

func Example() {
	type InfoRequest struct {
		Name   string `vd:"($!='Alice'||(Age)$==18) && regexp('\\w')"`
		Age    int    `vd:"$>0"`
		Email  string `vd:"email($)"`
		Phone1 string `vd:"phone($)"`
		Phone2 string `vd:"phone($,'CN')"`
	}
	info := InfoRequest{
		Name:   "Alice",
		Age:    18,
		Email:  "[email protected]",
		Phone1: "+8618812345678",
		Phone2: "18812345678",
	}
	fmt.Println(vd.Validate(info) == nil)

	type A struct {
		A    int `vd:"$<0||$>=100"`
		Info interface{}
	}
	info.Email = "xxx"
	a := &A{A: 107, Info: info}
	fmt.Println(vd.Validate(a))

	type B struct {
		B string `vd:"len($)>1 && regexp('^\\w*$')"`
	}
	b := &B{"abc"}
	fmt.Println(vd.Validate(b) == nil)

	type C struct {
		C bool `vd:"{@:(S.A)$>0 && !$}{msg:'C must be false when S.A>0'}"`
		S *A
	}
	c := &C{C: true, S: a}
	fmt.Println(vd.Validate(c))

	type D struct {
		d []string `vd:"{@:len($)>0 && $[0]=='D'} {msg:sprintf('invalid d: %v',$)}"`
	}
	d := &D{d: []string{"x", "y"}}
	fmt.Println(vd.Validate(d))

	type E struct {
		e map[string]int `vd:"len($)==$['len']"`
	}
	e := &E{map[string]int{"len": 2}}
	fmt.Println(vd.Validate(e))

	// Customizes the factory of validation error.
	vd.SetErrorFactory(func(failPath, msg string) error {
		return fmt.Errorf(`{"succ":false, "error":"validation failed: %s"}`, failPath)
	})

	type F struct {
		f struct {
			g int `vd:"$%3==0"`
		}
	}
	f := &F{}
	f.f.g = 10
	fmt.Println(vd.Validate(f))

	fmt.Println(vd.Validate(map[string]*F{"a": f}))
	fmt.Println(vd.Validate(map[*F]int{f: 1}))
	fmt.Println(vd.Validate([][1]*F{{f}}))
	fmt.Println(vd.Validate((*F)(nil)))
	fmt.Println(vd.Validate(map[string]*F{}))
	fmt.Println(vd.Validate([]*F{}))

	// Output:
	// true
	// invalid parameter: Email
	// true
	// C must be false when S.A>0
	// invalid d: [x y]
	// invalid parameter: e
	// {"succ":false, "error":"validation failed: f.g"}
	// {"succ":false, "error":"validation failed: a/f.g"}
	// {"succ":false, "error":"validation failed: {k}/f.g"}
	// {"succ":false, "error":"validation failed: 0/0/f.g"}
	// unsupport data: nil
	// <nil>
	// <nil>
}

Syntax

Struct tag syntax spec:

type T struct {
	// Simple model
    Field1 T1 `tagName:"expression"`
	// Specify error message mode
    Field2 T2 `tagName:"{@:expression}{msg:expression2}"`
    ...
}
Operator or OperandExplain
true falseboolean
0 0.0float64 "0"
''String
\\'Escape ' delims in string
\"Escape " delims in string
nilnil, undefined
!not, suitable for bool, string, float64, nil, $ and ()
+Digital addition or string splicing
-Digital subtraction or negative
*Digital multiplication
/Digital division
%division remainder, as: float64(int64(a)%int64(b))
==eq
!=ne
>gt
>=ge
<lt
<=le
&&Logic and
||Logic or
()Expression group
(X)$Struct field value named X
(X.Y)$Struct field value named X.Y
$Shorthand for (X)$, omit (X) to indicate current struct field value
(X)$['A']Map value with key A or struct A sub-field in the struct field X
(X)$[0]The 0th element or sub-field of the struct field X(type: map, slice, array, struct)
len((X)$)Built-in function len, the length of struct field X
regexp('^\\w*$', (X)$)Regular match the struct field X, return boolean
regexp('^\\w*$')Regular match the current struct field, return boolean
sprintf('X value: %v', (X)$)fmt.Sprintf, format the value of struct field X
email((X)$)Regular match the struct field X, return true if it is email
phone((X)$,<'defaultRegion'>)Regular match the struct field X, return true if it is phone

Operator priority(high -> low):

  • () ! bool float64 string nil
  • * / %
  • + -
  • < <= > >=
  • == !=
  • &&
  • ||

# Functions

Default returns the default validator.
New creates a struct fields validator.
RegFunc registers validator function expression.
SetErrorFactory customizes the factory of validation error for the default validator.
Validate uses the default validator to validate whether the fields of value is valid.

# Constants

ErrMsgExprName the name of the expression used to specify the message returned when validation failed.
MatchExprName the name of the expression used for validation.

# Structs

Error validate error.
Validator struct fields validator.