-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvalidator.go
156 lines (139 loc) · 4.18 KB
/
validator.go
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
package validator
import (
"errors"
"fmt"
"strings"
"github.com/admpub/log"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
"github.com/webx-top/echo"
)
var DefaultLocale = `zh`
func NormalizeLocale(locale string) string {
return strings.Replace(locale, `-`, `_`, -1)
}
func New(ctx echo.Context, locales ...string) *Validate {
var locale string
if len(locales) > 0 {
locale = locales[0]
}
if len(locale) == 0 {
locale = DefaultLocale
}
translator, _ := UniversalTranslator().GetTranslator(locale)
validate := validator.New()
transtation, ok := Translations[locale]
if !ok {
args := strings.SplitN(locale, `_`, 2)
if len(args) == 2 {
transtation, ok = Translations[args[0]]
} else {
log.Warnf(`[validator] not found translation: %s`, locale)
}
}
if ok {
transtation(validate, translator)
}
v := &Validate{
validator: validate,
translator: translator,
context: ctx,
}
regiterCustomValidationTranslator(v, translator, locale)
return v
}
type Validate struct {
validator *validator.Validate
translator ut.Translator
context echo.Context
}
func (v *Validate) Object() *validator.Validate {
return v.validator
}
func (v *Validate) Context() echo.Context {
return v.context
}
// ValidateMap validates map data form a map of tags
func (v *Validate) ValidateMap(data map[string]interface{}, rules map[string]interface{}) map[string]interface{} {
return v.validator.ValidateMapCtx(v.context, data, rules)
}
// Struct 接收的参数为一个struct
func (v *Validate) Struct(i interface{}) error {
return v.Error(v.validator.StructCtx(v.context, i))
}
// StructExcept 校验struct中的选项,不过除了fields里所给的字段
func (v *Validate) StructExcept(s interface{}, fields ...string) error {
return v.Error(v.validator.StructExceptCtx(v.context, s))
}
// StructFiltered 接收一个struct和一个函数,这个函数的返回值为bool,决定是否跳过该选项
func (v *Validate) StructFiltered(s interface{}, fn validator.FilterFunc) error {
return v.Error(v.validator.StructFilteredCtx(v.context, s, fn))
}
// StructPartial 接收一个struct和fields,仅校验在fields里的值
func (v *Validate) StructPartial(s interface{}, fields ...string) error {
return v.Error(v.validator.StructPartialCtx(v.context, s, fields...))
}
// Var 接收一个变量和一个tag的值,比如 validate.Var(i, "gt=1,lt=10")
func (v *Validate) Var(field interface{}, tag string) error {
return v.Error(v.validator.VarCtx(v.context, field, tag))
}
// VarWithValue 将两个变量进行对比,比如 validate.VarWithValue(s1, s2, "eqcsfield")
func (v *Validate) VarWithValue(field interface{}, other interface{}, tag string) error {
return v.Error(v.validator.VarWithValueCtx(v.context, field, other, tag))
}
// Validate 此处支持两种用法:
// 1. Validate(表单字段名, 表单值, 验证规则名)
// 2. Validate(结构体实例, 要验证的结构体字段1,要验证的结构体字段2)
// Validate(结构体实例) 代表验证所有带“valid”标签的字段
func (v *Validate) Validate(i interface{}, args ...interface{}) echo.ValidateResult {
e := echo.NewValidateResult()
var err error
switch m := i.(type) {
case string:
field := m
var value interface{}
var rule string
switch len(args) {
case 2:
rule = fmt.Sprint(args[1])
fallthrough
case 1:
value = args[0]
}
if len(rule) == 0 {
return e
}
err = v.validator.VarCtx(v.context, value, rule)
if err != nil {
e.SetField(field)
e.SetRaw(err)
return e.SetError(v.Error(err))
}
default:
if len(args) > 0 {
err = v.validator.StructPartialCtx(v.context, i, echo.InterfacesToStrings(args)...)
} else {
err = v.validator.StructCtx(v.context, i)
}
if err != nil {
vErrors := err.(validator.ValidationErrors)
e.SetField(vErrors[0].Field())
e.SetRaw(vErrors)
return e.SetError(v.Error(vErrors[0]))
}
}
return e
}
func (v *Validate) Error(err error) error {
if err == nil {
return nil
}
switch rErr := err.(type) {
case validator.FieldError:
return errors.New(rErr.Translate(v.translator))
case validator.ValidationErrors:
return errors.New(rErr[0].Translate(v.translator))
default:
return err
}
}