github.com/bytedance/go-tagexpr@v2.7.5-0.20210114074101-de5b8743ad85+incompatible/validator/README.md (about) 1 # validator [![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](http://godoc.org/github.com/bytedance/go-tagexpr/validator) 2 3 A powerful validator that supports struct tag expression. 4 5 ## Feature 6 7 - Support for a variety of common operator 8 - Support for accessing arrays, slices, members of the dictionary 9 - Support access to any field in the current structure 10 - Support access to nested fields, non-exported fields, etc. 11 - Support registers validator function expression 12 - Built-in len, sprintf, regexp, email, phone functions 13 - Support simple mode, or specify error message mode 14 - Use offset pointers to directly take values, better performance 15 - Required go version ≥1.9 16 17 ## Example 18 19 ```go 20 package validator_test 21 22 import ( 23 "fmt" 24 25 vd "github.com/bytedance/go-tagexpr/validator" 26 ) 27 28 func Example() { 29 type InfoRequest struct { 30 Name string `vd:"($!='Alice'||(Age)$==18) && regexp('\\w')"` 31 Age int `vd:"$>0"` 32 Email string `vd:"email($)"` 33 Phone1 string `vd:"phone($)"` 34 Phone2 string `vd:"phone($,'CN')"` 35 *InfoRequest `vd:"?"` 36 Info1 *InfoRequest `vd:"?"` 37 Info2 *InfoRequest `vd:"-"` 38 } 39 info := InfoRequest{ 40 Name: "Alice", 41 Age: 18, 42 Email: "henrylee2cn@gmail.com", 43 Phone1: "+8618812345678", 44 Phone2: "18812345678", 45 } 46 fmt.Println(vd.Validate(info) == nil) 47 48 type A struct { 49 A int `vd:"$<0||$>=100"` 50 Info interface{} 51 } 52 info.Email = "xxx" 53 a := &A{A: 107, Info: info} 54 fmt.Println(vd.Validate(a)) 55 56 type B struct { 57 B string `vd:"len($)>1 && regexp('^\\w*$')"` 58 } 59 b := &B{"abc"} 60 fmt.Println(vd.Validate(b) == nil) 61 62 type C struct { 63 C bool `vd:"@:(S.A)$>0 && !$; msg:'C must be false when S.A>0'"` 64 S *A 65 } 66 c := &C{C: true, S: a} 67 fmt.Println(vd.Validate(c)) 68 69 type D struct { 70 d []string `vd:"@:len($)>0 && $[0]=='D'; msg:sprintf('invalid d: %v',$)"` 71 } 72 d := &D{d: []string{"x", "y"}} 73 fmt.Println(vd.Validate(d)) 74 75 type E struct { 76 e map[string]int `vd:"len($)==$['len']"` 77 } 78 e := &E{map[string]int{"len": 2}} 79 fmt.Println(vd.Validate(e)) 80 81 // Customizes the factory of validation error. 82 vd.SetErrorFactory(func(failPath, msg string) error { 83 return fmt.Errorf(`{"succ":false, "error":"validation failed: %s"}`, failPath) 84 }) 85 86 type F struct { 87 f struct { 88 g int `vd:"$%3==0"` 89 } 90 } 91 f := &F{} 92 f.f.g = 10 93 fmt.Println(vd.Validate(f)) 94 95 fmt.Println(vd.Validate(map[string]*F{"a": f})) 96 fmt.Println(vd.Validate(map[*F]int{f: 1})) 97 fmt.Println(vd.Validate([][1]*F{{f}})) 98 fmt.Println(vd.Validate((*F)(nil))) 99 fmt.Println(vd.Validate(map[string]*F{})) 100 fmt.Println(vd.Validate([]*F{})) 101 102 // Output: 103 // true 104 // invalid parameter: Info.Email 105 // true 106 // C must be false when S.A>0 107 // invalid d: [x y] 108 // invalid parameter: e 109 // {"succ":false, "error":"validation failed: f.g"} 110 // {"succ":false, "error":"validation failed: {K:a}.f.g"} 111 // {"succ":false, "error":"validation failed: {}.f.g"} 112 // {"succ":false, "error":"validation failed: [0][0].f.g"} 113 // unsupport data: nil 114 // <nil> 115 // <nil> 116 } 117 ``` 118 119 ## Syntax 120 121 Struct tag syntax spec: 122 123 ``` 124 type T struct { 125 // Simple model 126 Field1 T1 `tagName:"expression"` 127 // Specify error message mode 128 Field2 T2 `tagName:"@:expression; msg:expression2"` 129 // Omit it 130 Field3 T3 `tagName:"-"` 131 // Omit it when it is nil 132 Field4 T4 `tagName:"?"` 133 ... 134 } 135 ``` 136 137 |Operator or Operand|Explain| 138 |-----|---------| 139 |`true` `false`|boolean| 140 |`0` `0.0`|float64 "0"| 141 |`''`|String| 142 |`\\'`| Escape `'` delims in string| 143 |`\"`| Escape `"` delims in string| 144 |`nil`|nil, undefined| 145 |`!`|not, suitable for `bool`, `string`, `float64`, `nil`, `$` and `()`| 146 |`+`|Digital addition or string splicing| 147 |`-`|Digital subtraction or negative| 148 |`*`|Digital multiplication| 149 |`/`|Digital division| 150 |`%`|division remainder, as: `float64(int64(a)%int64(b))`| 151 |`==`|`eq`| 152 |`!=`|`ne`| 153 |`>`|`gt`| 154 |`>=`|`ge`| 155 |`<`|`lt`| 156 |`<=`|`le`| 157 |`&&`|Logic `and`| 158 |`\|\|`|Logic `or`| 159 |`()`|Expression group| 160 |`(X)$`|Struct field value named X| 161 |`(X.Y)$`|Struct field value named X.Y| 162 |`$`|Shorthand for `(X)$`, omit `(X)` to indicate current struct field value| 163 |`(X)$['A']`|Map value with key A or struct A sub-field in the struct field X| 164 |`(X)$[0]`|The 0th element or sub-field of the struct field X(type: map, slice, array, struct)| 165 |`len((X)$)`|Built-in function `len`, the length of struct field X| 166 |`regexp('^\\w*$', (X)$)`|Regular match the struct field X, return boolean| 167 |`regexp('^\\w*$')`|Regular match the current struct field, return boolean| 168 |`sprintf('X value: %v', (X)$)`|`fmt.Sprintf`, format the value of struct field X| 169 |`email((X)$)`|Regular match the struct field X, return true if it is email| 170 |`phone((X)$,<'defaultRegion'>)`|Regular match the struct field X, return true if it is phone| 171 |`in((X)$, enum_1, ...enum_n)`|Check if the first parameter is one of the enumerated parameters| 172 173 <!-- |`(X)$k`|Traverse each element key of the struct field X(type: map, slice, array)| 174 |`(X)$v`|Traverse each element value of the struct field X(type: map, slice, array)| --> 175 176 <!-- |`&`|Integer bitwise `and`| 177 |`\|`|Integer bitwise `or`| 178 |`^`|Integer bitwise `not` or `xor`| 179 |`&^`|Integer bitwise `clean`| 180 |`<<`|Integer bitwise `shift left`| 181 |`>>`|Integer bitwise `shift right`| --> 182 183 Operator priority(high -> low): 184 185 * `()` `!` `bool` `float64` `string` `nil` 186 * `*` `/` `%` 187 * `+` `-` 188 * `<` `<=` `>` `>=` 189 * `==` `!=` 190 * `&&` 191 * `||`