@@ -2,12 +2,14 @@ package validation
2
2
3
3
import (
4
4
"errors"
5
+ "fmt"
5
6
"html/template"
6
7
"image"
7
8
"os"
8
9
"reflect"
9
10
"strconv"
10
11
"strings"
12
+ "time"
11
13
)
12
14
13
15
type Validation struct {
@@ -31,10 +33,10 @@ func (s *Validation) SetLanguage(lang map[string]string) {
31
33
s .Language = lang
32
34
}
33
35
34
- type ValidationErrors struct {
35
- Index string `json:"index,omitempty"`
36
- Key string `json:"key,omitempty"`
37
- Message []string `json:"message,omitempty"`
36
+ type ValidationErrorMessage struct {
37
+ Index string `json:"index,omitempty"`
38
+ Field string `json:"key,omitempty"`
39
+ Message []interface {} `json:"message,omitempty"`
38
40
}
39
41
40
42
func format (s string , v interface {}) string {
@@ -45,24 +47,26 @@ func format(s string, v interface{}) string {
45
47
return sb .String ()
46
48
}
47
49
48
- func (s * Validation ) Validate (data interface {}) ([]* ValidationErrors , error ) {
50
+ func (s * Validation ) Validate (data interface {}) ([]* ValidationErrorMessage , error ) {
49
51
typeT := reflect .TypeOf (data )
50
- out := make ([]* ValidationErrors , 0 )
52
+ typeV := reflect .ValueOf (data )
53
+ out := make ([]* ValidationErrorMessage , 0 )
51
54
for i := 0 ; i < typeT .NumField (); i ++ {
52
- field := typeT .Field (i )
55
+ fieldType := typeT .Field (i )
56
+ fieldValue := typeV .Field (i )
53
57
var key string
54
- if field .Tag .Get ("json" ) == "" {
55
- key = field .Name
58
+ if fieldType .Tag .Get ("json" ) == "" {
59
+ key = fieldType .Name
56
60
} else {
57
- key = strings .Split (field .Tag .Get ("json" ), "," )[0 ]
61
+ key = strings .Split (fieldType .Tag .Get ("json" ), "," )[0 ]
58
62
}
59
- validate := field . Tag . Get ( "validate" )
60
- if validate != "" {
61
- rules := strings . Split ( validate , "," )
62
- formErr := new ( ValidationErrors )
63
- msg := [] string {}
63
+
64
+ formErr := new ( ValidationErrorMessage )
65
+ msg := [] interface {}{}
66
+ if validate := fieldType . Tag . Get ( "validate" ); validate != "" {
67
+ rules := strings . Split ( strings . ReplaceAll ( validate , " " , "" ), "," )
64
68
for _ , rule := range rules {
65
- value := reflect .ValueOf (data ).FieldByName (field .Name )
69
+ value := reflect .ValueOf (data ).FieldByName (fieldType .Name )
66
70
rl := strings .Split (rule , "=" )
67
71
switch rl [0 ] {
68
72
case "eqfield" :
@@ -86,8 +90,34 @@ func (s *Validation) Validate(data interface{}) ([]*ValidationErrors, error) {
86
90
}
87
91
}
88
92
case "required" :
89
- if ! isRequired (value ) {
90
- msg = append (msg , s .Language ["required" ])
93
+ switch value .Kind () {
94
+ case reflect .Slice :
95
+ if value .Len () == 0 {
96
+ msg = append (msg , s .Language ["required" ])
97
+ }
98
+ for j := 0 ; j < value .Len (); j ++ {
99
+ validationErrorMessage , err := s .Validate (value .Index (j ).Interface ())
100
+ if err != nil {
101
+ for _ , a := range validationErrorMessage {
102
+ msg = append (msg , a )
103
+ }
104
+ }
105
+ }
106
+ case reflect .String :
107
+ if ! isRequired (value ) {
108
+ msg = append (msg , s .Language ["required" ])
109
+ }
110
+ case reflect .Struct :
111
+ if value .Type () == reflect .TypeOf (time.Time {}) {
112
+ if value .Interface ().(time.Time ).IsZero () {
113
+ msg = append (msg , s .Language ["required" ])
114
+ }
115
+ }
116
+ case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
117
+ if value .Int () == 0 {
118
+ msg = append (msg , s .Language ["required" ])
119
+ // return fmt.Errorf("field %s is required and must not be 0", fieldType.Name)
120
+ }
91
121
}
92
122
case "alpha" :
93
123
if ! isAlpha (value ) {
@@ -143,11 +173,20 @@ func (s *Validation) Validate(data interface{}) ([]*ValidationErrors, error) {
143
173
}
144
174
}
145
175
}
146
- if len (msg ) > 0 {
147
- formErr .Message = msg
148
- formErr .Key = key
149
- out = append (out , formErr )
176
+ }
177
+ if enumTag := fieldType .Tag .Get ("enum" ); enumTag != "" {
178
+ allowedValues := map [string ]bool {}
179
+ for _ , val := range split (enumTag , "," ) {
180
+ allowedValues [val ] = true
150
181
}
182
+ if ! allowedValues [fieldValue .String ()] {
183
+ msg = append (msg , format (s .Language ["enum" ], fmt .Sprintf ("[%s]" , enumTag )))
184
+ }
185
+ }
186
+ if len (msg ) > 0 {
187
+ formErr .Message = msg
188
+ formErr .Field = key
189
+ out = append (out , formErr )
151
190
}
152
191
}
153
192
if len (out ) > 0 {
@@ -156,9 +195,9 @@ func (s *Validation) Validate(data interface{}) ([]*ValidationErrors, error) {
156
195
return nil , nil
157
196
}
158
197
159
- func (s * Validation ) FileValidate (f * os.File , rules string ) (* ValidationErrors , error ) {
160
- formErr := new (ValidationErrors )
161
- msg := []string {}
198
+ func (s * Validation ) FileValidate (f * os.File , rules string ) (* ValidationErrorMessage , error ) {
199
+ formErr := new (ValidationErrorMessage )
200
+ msg := []interface {} {}
162
201
163
202
for _ , v := range strings .Split (rules , "," ) {
164
203
rv := strings .Split (v , "=" )
@@ -203,8 +242,21 @@ func (s *Validation) FileValidate(f *os.File, rules string) (*ValidationErrors,
203
242
}
204
243
if len (msg ) > 0 {
205
244
formErr .Message = msg
206
- formErr .Key = f .Name ()
245
+ formErr .Field = f .Name ()
207
246
return formErr , errors .New ("form error" )
208
247
}
209
248
return nil , nil
210
249
}
250
+
251
+ func split (s string , delim string ) []string {
252
+ var result []string
253
+ start := 0
254
+ for i := 0 ; i < len (s ); i ++ {
255
+ if string (s [i ]) == delim {
256
+ result = append (result , s [start :i ])
257
+ start = i + 1
258
+ }
259
+ }
260
+ result = append (result , s [start :])
261
+ return result
262
+ }
0 commit comments