github.com/bytedance/go-tagexpr/v2@v2.9.8/validator/README.md (about) 1 # validator [](http://godoc.org/github.com/bytedance/go-tagexpr/v2/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/v2/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 OtherPhones []string `vd:"range($, phone(#v,'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 OtherPhones: []string{"18812345679", "18812345680"}, 45 } 46 fmt.Println(vd.Validate(info)) 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 type B struct { 56 B string `vd:"len($)>1 && regexp('^\\w*$')"` 57 } 58 b := &B{"abc"} 59 fmt.Println(vd.Validate(b) == nil) 60 61 type C struct { 62 C bool `vd:"@:(S.A)$>0 && !$; msg:'C must be false when S.A>0'"` 63 S *A 64 } 65 c := &C{C: true, S: a} 66 fmt.Println(vd.Validate(c)) 67 68 type D struct { 69 d []string `vd:"@:len($)>0 && $[0]=='D'; msg:sprintf('invalid d: %v',$)"` 70 } 71 d := &D{d: []string{"x", "y"}} 72 fmt.Println(vd.Validate(d)) 73 74 type E struct { 75 e map[string]int `vd:"len($)==$['len']"` 76 } 77 e := &E{map[string]int{"len": 2}} 78 fmt.Println(vd.Validate(e)) 79 80 // Customizes the factory of validation error. 81 vd.SetErrorFactory(func(failPath, msg string) error { 82 return fmt.Errorf(`{"succ":false, "error":"validation failed: %s"}`, failPath) 83 }) 84 85 type F struct { 86 f struct { 87 g int `vd:"$%3==0"` 88 } 89 } 90 f := &F{} 91 f.f.g = 10 92 fmt.Println(vd.Validate(f)) 93 94 fmt.Println(vd.Validate(map[string]*F{"a": f})) 95 fmt.Println(vd.Validate(map[string]map[string]*F{"a": {"b": f}})) 96 fmt.Println(vd.Validate([]map[string]*F{{"a": f}})) 97 fmt.Println(vd.Validate(struct { 98 A []map[string]*F 99 }{A: []map[string]*F{{"x": f}}})) 100 fmt.Println(vd.Validate(map[*F]int{f: 1})) 101 fmt.Println(vd.Validate([][1]*F{{f}})) 102 fmt.Println(vd.Validate((*F)(nil))) 103 fmt.Println(vd.Validate(map[string]*F{})) 104 fmt.Println(vd.Validate(map[string]map[string]*F{})) 105 fmt.Println(vd.Validate([]map[string]*F{})) 106 fmt.Println(vd.Validate([]*F{})) 107 108 // Output: 109 // <nil> 110 // email format is incorrect 111 // true 112 // C must be false when S.A>0 113 // invalid d: [x y] 114 // invalid parameter: e 115 // {"succ":false, "error":"validation failed: f.g"} 116 // {"succ":false, "error":"validation failed: {v for k=a}.f.g"} 117 // {"succ":false, "error":"validation failed: {v for k=a}{v for k=b}.f.g"} 118 // {"succ":false, "error":"validation failed: [0]{v for k=a}.f.g"} 119 // {"succ":false, "error":"validation failed: A[0]{v for k=x}.f.g"} 120 // {"succ":false, "error":"validation failed: {k}.f.g"} 121 // {"succ":false, "error":"validation failed: [0][0].f.g"} 122 // unsupport data: nil 123 // <nil> 124 // <nil> 125 // <nil> 126 // <nil> 127 } 128 ``` 129 130 ## Syntax 131 132 Struct tag syntax spec: 133 134 ``` 135 type T struct { 136 // Simple model 137 Field1 T1 `tagName:"expression"` 138 // Specify error message mode 139 Field2 T2 `tagName:"@:expression; msg:expression2"` 140 // Omit it 141 Field3 T3 `tagName:"-"` 142 // Omit it when it is nil 143 Field4 T4 `tagName:"?"` 144 ... 145 } 146 ``` 147 148 |Operator or Operand|Explain| 149 |-----|---------| 150 |`true` `false`|boolean| 151 |`0` `0.0`|float64 "0"| 152 |`''`|String| 153 |`\\'`| Escape `'` delims in string| 154 |`\"`| Escape `"` delims in string| 155 |`nil`|nil, undefined| 156 |`!`|not| 157 |`+`|Digital addition or string splicing| 158 |`-`|Digital subtraction or negative| 159 |`*`|Digital multiplication| 160 |`/`|Digital division| 161 |`%`|division remainder, as: `float64(int64(a)%int64(b))`| 162 |`==`|`eq`| 163 |`!=`|`ne`| 164 |`>`|`gt`| 165 |`>=`|`ge`| 166 |`<`|`lt`| 167 |`<=`|`le`| 168 |`&&`|Logic `and`| 169 |`\|\|`|Logic `or`| 170 |`()`|Expression group| 171 |`(X)$`|Struct field value named X| 172 |`(X.Y)$`|Struct field value named X.Y| 173 |`$`|Shorthand for `(X)$`, omit `(X)` to indicate current struct field value| 174 |`(X)$['A']`|Map value with key A or struct A sub-field in the struct field X| 175 |`(X)$[0]`|The 0th element or sub-field of the struct field X(type: map, slice, array, struct)| 176 |`len((X)$)`|Built-in function `len`, the length of struct field X| 177 |`mblen((X)$)`|the length of string field X (character number)| 178 |`regexp('^\\w*$', (X)$)`|Regular match the struct field X, return boolean| 179 |`regexp('^\\w*$')`|Regular match the current struct field, return boolean| 180 |`sprintf('X value: %v', (X)$)`|`fmt.Sprintf`, format the value of struct field X| 181 |`range(KvExpr, forEachExpr)`|Iterate over an array, slice, or dictionary <br> - `#k` is the element key var <br> - `#v` is the element value var <br> - `##` is the number of elements <br> - e.g. [example](../spec_range_test.go)| 182 |`in((X)$, enum_1, ...enum_n)`|Check if the first parameter is one of the enumerated parameters| 183 |`email((X)$)`|Regular match the struct field X, return true if it is email| 184 |`phone((X)$,<'defaultRegion'>)`|Regular match the struct field X, return true if it is phone| 185 186 <!-- |`(X)$k`|Traverse each element key of the struct field X(type: map, slice, array)| 187 |`(X)$v`|Traverse each element value of the struct field X(type: map, slice, array)| --> 188 189 <!-- |`&`|Integer bitwise `and`| 190 |`\|`|Integer bitwise `or`| 191 |`^`|Integer bitwise `not` or `xor`| 192 |`&^`|Integer bitwise `clean`| 193 |`<<`|Integer bitwise `shift left`| 194 |`>>`|Integer bitwise `shift right`| --> 195 196 Operator priority(high -> low): 197 198 * `()` `!` `bool` `float64` `string` `nil` 199 * `*` `/` `%` 200 * `+` `-` 201 * `<` `<=` `>` `>=` 202 * `==` `!=` 203 * `&&` 204 * `||`