Repository navigation
Expand file tree
/
Copy pathvalidator.go
More file actions
172 lines (153 loc) · 4.76 KB
/
Copy pathvalidator.go
File metadata and controls
172 lines (153 loc) · 4.76 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
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 {
transtation, locale := getTranslationRegister(locales...)
return newWithTranslationRegister(ctx, transtation, locale)
}
func getTranslationRegister(locales ...string) (TranslationRegister, string) {
var locale string
if len(locales) > 0 {
locale = locales[0]
}
if len(locale) == 0 {
locale = DefaultLocale
}
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 locale != DefaultLocale {
log.Warnf(`[validator] fallback to default translation: %s`, DefaultLocale)
locale = DefaultLocale
transtation, ok = Translations[locale]
}
}
}
return transtation, locale
}
func newWithTranslationRegister(ctx echo.Context, transtation TranslationRegister, locale string) *Validate {
translator, _ := UniversalTranslator().GetTranslator(locale)
validate := validator.New()
if transtation != nil {
transtation(validate, translator)
}
v := &Validate{
locale: locale,
validator: validate,
translator: translator,
context: ctx,
}
regiterCustomValidationTranslator(v, translator, locale)
return v
}
type Validate struct {
locale string
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
}
}