-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvalidator.go
More file actions
335 lines (264 loc) · 7.89 KB
/
validator.go
File metadata and controls
335 lines (264 loc) · 7.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
package validator
import (
_ "fmt"
"reflect"
"strings"
)
const (
STR_NULL string = "null" // 空字符串
STR_REQUIRED string = "required" // 必须字符串
STR_UNDEFINE string = "undefine" // 未定义字符串
STR_SOMETIMES string = "sometimes" // 存在时字符串
STR_DEFAULT string = "default" // 默认字符串
STR_VALID string = "valid" // Tag验证关键字
ERR_ATTR_FUNC string = ":func" // 函数占位符
ERR_ATTR_ATTRIBUTE string = ":attribute" // 属性字段占位符
ERR_ATTR_VALUE string = ":value" // 值占位符
)
var (
// 设置相关的验证规则
ruleMap map[string]interface{}
// 设置字段的数据类型
typeMap map[string]interface{}
// 设置数据的值
dataMap map[string]interface{}
)
type Validator struct {
// 是否验证通过
Fails bool
// 自定义验证方法
TagMap map[string]func(...reflect.Value) bool
// 设置错误信息
ErrorMsg map[string]string
}
// New 实例化验证器
func New() *Validator {
validator := &Validator{
Fails: true,
TagMap: make(map[string]func(...reflect.Value) bool),
ErrorMsg: make(map[string]string),
}
ruleMap = make(map[string]interface{})
typeMap = make(map[string]interface{})
dataMap = make(map[string]interface{})
return validator
}
// Struct 结构体验证
func (v *Validator) Struct(obj interface{}) *Validator {
objT := reflect.TypeOf(obj)
objV := reflect.ValueOf(obj)
v.parseData(objT, objV)
return v
}
// Validate 执行验证
func (v *Validator) Validate() {
v.doParse()
}
// 数据解析处理
func (v *Validator) parseData(objT reflect.Type, objV reflect.Value) {
objName := objT.Name()
for i := 0; i < objT.NumField(); i++ {
ruleKey := objName + "." + objT.Field(i).Name
ruleVal := objT.Field(i).Tag.Get(STR_VALID)
ruleVal = strings.TrimSpace(ruleVal)
typeMap[ruleKey+".type"] = objT.Field(i).Type.Kind().String()
dataMap[ruleKey+".val"] = objV.Field(i)
v.parseRule(ruleKey, ruleVal)
}
}
// 解析规则,把字符串通过分隔符转换成规则map
func (v *Validator) parseRule(ruleKey string, rules string) {
if rules == "" || len(rules) <= 0 {
panic("rule error: Missing validation rules.")
}
ruleArr := strings.Split(rules, "|")
for _, rule := range ruleArr {
var tempKey string
val := STR_NULL
pos := strings.IndexAny(rule, ":")
if pos != -1 {
tempKey = rule[:pos]
val = rule[pos+1:]
} else {
tempKey = rule
}
// 去除相关空白字符
tempKey = strings.TrimSpace(tempKey)
val = strings.TrimSpace(val)
ruleMap[ruleKey+"."+tempKey] = val
}
}
// 执行解析
// 解析优先使用rule中的相关方法,如果不存在看是否存在用户自定义的方法,如果都没有则返回false,并添加到相关的错误中
func (v *Validator) doParse() {
if ruleMap != nil && typeMap != nil {
rule := NewRule()
rT := reflect.TypeOf(rule)
for key, val := range ruleMap {
pos := strings.LastIndexAny(key, ".")
method := Ucfirst(key[pos+1:])
fieldKey := key[:pos]
fieldType := typeMap[fieldKey+".type"]
fieldTemp := dataMap[fieldKey+".val"]
fieldVal, _ := fieldTemp.(reflect.Value)
// 检查传的值是否有效
if !fieldVal.IsValid() {
v.AddErrorMsg(key, strings.ToLower(method), STR_NULL, fieldType)
continue
}
callMethod, exist := rT.MethodByName(method)
if exist {
// 固定参数
params := make([]reflect.Value, 4)
// 指定使用的验证规则,参数是方法名
params[0] = reflect.ValueOf(rule)
// 指定验证规则内容
params[1] = reflect.ValueOf(val)
// 数据类型,字符串
params[2] = reflect.ValueOf(fieldType)
// 待验证的数据
params[3] = reflect.ValueOf(fieldVal)
// 通过反射调用已封装好的验证方法
retArr := callMethod.Func.Call(params)
ret := retArr[0].Bool()
if ret == false {
v.AddErrorMsg(key, method, val, fieldType)
}
} else {
// 方法名统一转化为小写
lowerMethod := strings.ToLower(method)
defineFunc, isSet := v.TagMap[lowerMethod]
if isSet {
// 执行用户自定义的验证方法,
// 第一个参数验证规则具体内容
// 第二个参数字段数据类型
// 第三个参数待验证的数据
ret := defineFunc(reflect.ValueOf(val), reflect.ValueOf(fieldType), fieldVal)
if ret == false {
v.AddErrorMsg(key, lowerMethod, val, fieldType)
}
} else {
v.AddFuncErrorMsg(key, lowerMethod)
}
}
}
}
}
// AddRule 逐条添加指定的验证规则
func (v *Validator) AddRule(fieldKey, fieldType, ruleStr string, dataVal interface{}) *Validator {
typeMap[fieldKey+".type"] = fieldType
dataMap[fieldKey+".val"] = reflect.ValueOf(dataVal)
v.parseRule(fieldKey, ruleStr)
return v
}
// AddMapRule 批量通过map添加指定验证规则
func (v *Validator) AddMapRule(ruleMap map[string][]string, dataVal map[string]interface{}) *Validator {
for key, tag := range ruleMap {
if len(tag) < 2 {
panic("rule error: At least two " + key + " elements.")
}
tempData, ok := dataVal[key]
var data interface{}
if ok && reflect.ValueOf(tempData).IsValid() {
data = tempData
} else {
if v.ContainSometimes(tag[1]) {
continue
}
if v.ContainRequired(tag[1]) {
v.AddErrorMsg(key+".required", STR_REQUIRED, STR_NULL, nil)
continue
}
v.AddErrorMsg(key, STR_NULL, STR_NULL, nil)
continue
}
v.AddRule(key, tag[0], tag[1], data)
}
return v
}
// AddFuncErrorMsg 添加未定义func错误信息
func (v *Validator) AddFuncErrorMsg(fieldKey, attribute interface{}) {
keyStr := reflect.ValueOf(fieldKey).String()
method := reflect.ValueOf(attribute).String()
method = strings.ToLower(method)
errMsg := ""
errStr, ok := ruleErrorMsgMap[STR_UNDEFINE]
if ok {
errMsg = reflect.ValueOf(errStr).String()
errMsg = strings.Replace(errMsg, ERR_ATTR_FUNC, method, -1)
} else {
errMsg = "The func " + method + "() is not defined."
}
v.Fails = false
_, err := v.ErrorMsg[keyStr]
if !err {
v.ErrorMsg[keyStr] = errMsg
}
}
// AddErrorMsg 添加错误信息到error map中
func (v *Validator) AddErrorMsg(fieldKey, attribute, value, filedType interface{}) {
keyStr := reflect.ValueOf(fieldKey).String()
valStr := reflect.ValueOf(value).String()
method := reflect.ValueOf(attribute).String()
method = strings.ToLower(method)
filedStr := strings.Replace(keyStr, "."+method, "", -1)
errMsg := ""
errStr, exits := ruleErrorMsgMap[method]
if exits {
asType := getTypeMapping(reflect.ValueOf(filedType).String())
var msgIndex = "string"
switch errStr.(type) {
case string:
msgIndex = "string"
default:
msgIndex = "noString"
}
if msgIndex == "noString" {
tempMap := errStr.(map[string]string)
errMsg = tempMap[asType]
} else {
errMsg = reflect.ValueOf(errStr).String()
}
errMsg = strings.Replace(errMsg, ERR_ATTR_ATTRIBUTE, filedStr, -1)
errMsg = strings.Replace(errMsg, ERR_ATTR_VALUE, valStr, -1)
} else {
defaultStr, ok := ruleErrorMsgMap[STR_DEFAULT]
if ok {
errMsg = reflect.ValueOf(defaultStr).String()
errMsg = strings.Replace(errMsg, ERR_ATTR_ATTRIBUTE, filedStr, -1)
} else {
errMsg = "The " + filedStr + " is invalid."
}
}
v.Fails = false
_, ok := v.ErrorMsg[keyStr]
if !ok {
v.ErrorMsg[keyStr] = errMsg
}
}
// ContainRequired 验证规则是否包含required
func (v *Validator) ContainRequired(sRule string) bool {
str := string([]rune(sRule))
pos := strings.Index(str, STR_REQUIRED)
if pos != -1 {
return true
}
return false
}
// ContainSometimes 验证规则是否包含sometimes
func (v *Validator) ContainSometimes(sRule string) bool {
str := string([]rune(sRule))
pos := strings.Index(str, STR_SOMETIMES)
if pos != -1 {
return true
}
return false
}
// ClearError 清除验证
func (v *Validator) ClearError() {
v.Fails = true
v.ErrorMsg = make(map[string]string)
ruleMap = make(map[string]interface{})
typeMap = make(map[string]interface{})
dataMap = make(map[string]interface{})
}