model.go raw
1 package dara
2
3 import (
4 "encoding/json"
5 "errors"
6 "fmt"
7 "reflect"
8 "regexp"
9 "strconv"
10 "strings"
11 )
12
13 type Model interface {
14 Validate() error
15 ToMap() map[string]interface{}
16 copyWithouStream() Model
17 }
18
19 func Validate(params interface{}) error {
20 if params == nil {
21 return nil
22 }
23 requestValue := reflect.ValueOf(params)
24 if requestValue.IsNil() {
25 return nil
26 }
27 err := validate(requestValue.Elem())
28 return err
29 }
30
31 // ValidateRequired checks if a value is set (non-nil)
32 func ValidateRequired(value interface{}, fieldName string) error {
33 if value == nil {
34 return errors.New(fieldName + " should be setted")
35 }
36
37 // Check for typed nil pointers
38 switch v := value.(type) {
39 case *string:
40 if v == nil {
41 return errors.New(fieldName + " should be setted")
42 }
43 case *int:
44 if v == nil {
45 return errors.New(fieldName + " should be setted")
46 }
47 case *int8:
48 if v == nil {
49 return errors.New(fieldName + " should be setted")
50 }
51 case *int16:
52 if v == nil {
53 return errors.New(fieldName + " should be setted")
54 }
55 case *int32:
56 if v == nil {
57 return errors.New(fieldName + " should be setted")
58 }
59 case *int64:
60 if v == nil {
61 return errors.New(fieldName + " should be setted")
62 }
63 case *uint:
64 if v == nil {
65 return errors.New(fieldName + " should be setted")
66 }
67 case *uint8:
68 if v == nil {
69 return errors.New(fieldName + " should be setted")
70 }
71 case *uint16:
72 if v == nil {
73 return errors.New(fieldName + " should be setted")
74 }
75 case *uint32:
76 if v == nil {
77 return errors.New(fieldName + " should be setted")
78 }
79 case *uint64:
80 if v == nil {
81 return errors.New(fieldName + " should be setted")
82 }
83 case *float32:
84 if v == nil {
85 return errors.New(fieldName + " should be setted")
86 }
87 case *float64:
88 if v == nil {
89 return errors.New(fieldName + " should be setted")
90 }
91 }
92
93 return nil
94 }
95
96 // ValidateMaxLength validates maximum length using type assertions
97 func ValidateMaxLength(value interface{}, maxLength int, fieldName string) error {
98 length := getValueLength(value)
99 if length > maxLength {
100 return fmt.Errorf("The length of %s is %d which is more than %d", fieldName, length, maxLength)
101 }
102 return nil
103 }
104
105 // ValidateMinLength validates minimum length using type assertions
106 func ValidateMinLength(value interface{}, minLength int, fieldName string) error {
107 length := getValueLength(value)
108 if length < minLength {
109 return fmt.Errorf("The length of %s is %d which is less than %d", fieldName, length, minLength)
110 }
111 return nil
112 }
113
114 // ValidatePattern validates string against regex pattern
115 func ValidatePattern(value interface{}, pattern string, fieldName string) error {
116 strValue := getStringValue(value)
117 if strValue == "" {
118 return nil // Empty strings are valid unless required
119 }
120
121 r, err := regexp.Compile("^" + pattern + "$")
122 if err != nil {
123 return err
124 }
125
126 if !r.MatchString(strValue) {
127 return errors.New(strValue + " is not matched " + pattern)
128 }
129 return nil
130 }
131
132 // ValidateMaximum validates maximum value for numeric types
133 func ValidateMaximum(value interface{}, maximum float64, fieldName string) error {
134 numValue, ok := getNumericValue(value)
135 if !ok {
136 return nil // Skip validation for non-numeric types
137 }
138
139 if numValue > maximum {
140 return fmt.Errorf("The size of %s is %f which is greater than %f", fieldName, numValue, maximum)
141 }
142 return nil
143 }
144
145 // ValidateMinimum validates minimum value for numeric types
146 func ValidateMinimum(value interface{}, minimum float64, fieldName string) error {
147 numValue, ok := getNumericValue(value)
148 if !ok {
149 return nil // Skip validation for non-numeric types
150 }
151
152 if numValue < minimum {
153 return fmt.Errorf("The size of %s is %f which is less than %f", fieldName, numValue, minimum)
154 }
155 return nil
156 }
157
158 // ValidateArray validates array/slice elements recursively
159 func ValidateArray(arr interface{}, validator func(interface{}) error) error {
160 switch v := arr.(type) {
161 case []interface{}:
162 for _, item := range v {
163 if err := validator(item); err != nil {
164 return err
165 }
166 }
167 case []*string:
168 for _, item := range v {
169 if err := validator(item); err != nil {
170 return err
171 }
172 }
173 case []*int:
174 for _, item := range v {
175 if err := validator(item); err != nil {
176 return err
177 }
178 }
179 // Add more specific types as needed
180 }
181 return nil
182 }
183
184 // ValidateMap validates map values recursively
185 func ValidateMap(m interface{}, validator func(interface{}) error) error {
186 switch v := m.(type) {
187 case map[string]interface{}:
188 for _, value := range v {
189 if err := validator(value); err != nil {
190 return err
191 }
192 }
193 case map[string]*string:
194 for _, value := range v {
195 if err := validator(value); err != nil {
196 return err
197 }
198 }
199 // Add more specific types as needed
200 }
201 return nil
202 }
203
204 // Helper functions using pure type assertions (no reflection)
205
206 // getStringValue extracts string value using type assertions
207 func getStringValue(value interface{}) string {
208 switch v := value.(type) {
209 case string:
210 return v
211 case *string:
212 if v != nil {
213 return *v
214 }
215 return ""
216 default:
217 return ""
218 }
219 }
220
221 // getNumericValue extracts numeric value as float64 using type assertions
222 func getNumericValue(value interface{}) (float64, bool) {
223 switch v := value.(type) {
224 // Direct numeric types
225 case int:
226 return float64(v), true
227 case int8:
228 return float64(v), true
229 case int16:
230 return float64(v), true
231 case int32:
232 return float64(v), true
233 case int64:
234 return float64(v), true
235 case uint:
236 return float64(v), true
237 case uint8:
238 return float64(v), true
239 case uint16:
240 return float64(v), true
241 case uint32:
242 return float64(v), true
243 case uint64:
244 return float64(v), true
245 case float32:
246 return float64(v), true
247 case float64:
248 return v, true
249
250 // Pointer types
251 case *int:
252 if v != nil {
253 return float64(*v), true
254 }
255 case *int8:
256 if v != nil {
257 return float64(*v), true
258 }
259 case *int16:
260 if v != nil {
261 return float64(*v), true
262 }
263 case *int32:
264 if v != nil {
265 return float64(*v), true
266 }
267 case *int64:
268 if v != nil {
269 return float64(*v), true
270 }
271 case *uint:
272 if v != nil {
273 return float64(*v), true
274 }
275 case *uint8:
276 if v != nil {
277 return float64(*v), true
278 }
279 case *uint16:
280 if v != nil {
281 return float64(*v), true
282 }
283 case *uint32:
284 if v != nil {
285 return float64(*v), true
286 }
287 case *uint64:
288 if v != nil {
289 return float64(*v), true
290 }
291 case *float32:
292 if v != nil {
293 return float64(*v), true
294 }
295 case *float64:
296 if v != nil {
297 return *v, true
298 }
299 default:
300 return 0, false
301 }
302 return 0, false
303 }
304
305 // getValueLength returns length of string, array, slice, or map using type assertions
306 func getValueLength(value interface{}) int {
307 switch v := value.(type) {
308 case string:
309 // Use the same method as original implementation for consistency
310 return len([]rune(v))
311 case *string:
312 if v != nil {
313 return len([]rune(*v))
314 }
315 return 0
316 case []interface{}:
317 return len(v)
318 case []string:
319 return len(v)
320 case []*string:
321 return len(v)
322 case []int:
323 return len(v)
324 case []*int:
325 return len(v)
326 case map[string]interface{}:
327 return len(v)
328 case map[string]string:
329 return len(v)
330 case map[string]*string:
331 return len(v)
332 // Add more specific types as needed
333 default:
334 return 0
335 }
336 }
337
338 // Deprecated: use new validation methods instead
339 // Verify whether the parameters meet the requirements
340 func validate(dataValue reflect.Value) error {
341 if strings.HasPrefix(dataValue.Type().String(), "*") { // Determines whether the input is a structure object or a pointer object
342 if dataValue.IsNil() {
343 return nil
344 }
345 dataValue = dataValue.Elem()
346 }
347 dataType := dataValue.Type()
348 for i := 0; i < dataType.NumField(); i++ {
349 field := dataType.Field(i)
350 valueField := dataValue.Field(i)
351 for _, value := range validateParams {
352 err := validateParam(field, valueField, value)
353 if err != nil {
354 return err
355 }
356 }
357 }
358 return nil
359 }
360
361 func validateParam(field reflect.StructField, valueField reflect.Value, tagName string) error {
362 tag, containsTag := field.Tag.Lookup(tagName) // Take out the checked regular expression
363 if containsTag && tagName == "require" {
364 err := checkRequire(field, valueField)
365 if err != nil {
366 return err
367 }
368 }
369 if strings.HasPrefix(field.Type.String(), "[]") { // Verify the parameters of the array type
370 err := validateSlice(field, valueField, containsTag, tag, tagName)
371 if err != nil {
372 return err
373 }
374 } else if valueField.Kind() == reflect.Ptr { // Determines whether it is a pointer object
375 err := validatePtr(field, valueField, containsTag, tag, tagName)
376 if err != nil {
377 return err
378 }
379 }
380 return nil
381 }
382
383 func validateSlice(field reflect.StructField, valueField reflect.Value, containsregexpTag bool, tag, tagName string) error {
384 if valueField.IsValid() && !valueField.IsNil() { // Determines whether the parameter has a value
385 if containsregexpTag {
386 if tagName == "maxItems" {
387 err := checkMaxItems(field, valueField, tag)
388 if err != nil {
389 return err
390 }
391 }
392
393 if tagName == "minItems" {
394 err := checkMinItems(field, valueField, tag)
395 if err != nil {
396 return err
397 }
398 }
399 }
400
401 for m := 0; m < valueField.Len(); m++ {
402 elementValue := valueField.Index(m)
403 if elementValue.Type().Kind() == reflect.Ptr { // Determines whether the child elements of an array are of a basic type
404 err := validatePtr(field, elementValue, containsregexpTag, tag, tagName)
405 if err != nil {
406 return err
407 }
408 }
409 }
410 }
411 return nil
412 }
413
414 func validatePtr(field reflect.StructField, elementValue reflect.Value, containsregexpTag bool, tag, tagName string) error {
415 if elementValue.IsNil() {
416 return nil
417 }
418 if isFilterType(elementValue.Elem().Type().String(), basicTypes) {
419 if containsregexpTag {
420 if tagName == "pattern" {
421 err := checkPattern(field, elementValue.Elem(), tag)
422 if err != nil {
423 return err
424 }
425 }
426
427 if tagName == "maxLength" {
428 err := checkMaxLength(field, elementValue.Elem(), tag)
429 if err != nil {
430 return err
431 }
432 }
433
434 if tagName == "minLength" {
435 err := checkMinLength(field, elementValue.Elem(), tag)
436 if err != nil {
437 return err
438 }
439 }
440
441 if tagName == "maximum" {
442 err := checkMaximum(field, elementValue.Elem(), tag)
443 if err != nil {
444 return err
445 }
446 }
447
448 if tagName == "minimum" {
449 err := checkMinimum(field, elementValue.Elem(), tag)
450 if err != nil {
451 return err
452 }
453 }
454 }
455 } else {
456 err := validate(elementValue)
457 if err != nil {
458 return err
459 }
460 }
461 return nil
462 }
463
464 func checkRequire(field reflect.StructField, valueField reflect.Value) error {
465 name, _ := field.Tag.Lookup("json")
466 strs := strings.Split(name, ",")
467 name = strs[0]
468 if !valueField.IsNil() && valueField.IsValid() {
469 return nil
470 }
471 return errors.New(name + " should be setted")
472 }
473
474 func checkPattern(field reflect.StructField, valueField reflect.Value, tag string) error {
475 if valueField.IsValid() && valueField.String() != "" {
476 value := valueField.String()
477 r, _ := regexp.Compile("^" + tag + "$")
478 if match := r.MatchString(value); !match { // Determines whether the parameter value satisfies the regular expression or not, and throws an error
479 return errors.New(value + " is not matched " + tag)
480 }
481 }
482 return nil
483 }
484
485 func checkMaxItems(field reflect.StructField, valueField reflect.Value, tag string) error {
486 if valueField.IsValid() && valueField.String() != "" {
487 maxItems, err := strconv.Atoi(tag)
488 if err != nil {
489 return err
490 }
491 length := valueField.Len()
492 if maxItems < length {
493 errMsg := fmt.Sprintf("The length of %s is %d which is more than %d", field.Name, length, maxItems)
494 return errors.New(errMsg)
495 }
496 }
497 return nil
498 }
499
500 func checkMinItems(field reflect.StructField, valueField reflect.Value, tag string) error {
501 if valueField.IsValid() {
502 minItems, err := strconv.Atoi(tag)
503 if err != nil {
504 return err
505 }
506 length := valueField.Len()
507 if minItems > length {
508 errMsg := fmt.Sprintf("The length of %s is %d which is less than %d", field.Name, length, minItems)
509 return errors.New(errMsg)
510 }
511 }
512 return nil
513 }
514
515 func checkMaxLength(field reflect.StructField, valueField reflect.Value, tag string) error {
516 if valueField.IsValid() && valueField.String() != "" {
517 maxLength, err := strconv.Atoi(tag)
518 if err != nil {
519 return err
520 }
521 length := valueField.Len()
522 if valueField.Kind().String() == "string" {
523 length = strings.Count(valueField.String(), "") - 1
524 }
525 if maxLength < length {
526 errMsg := fmt.Sprintf("The length of %s is %d which is more than %d", field.Name, length, maxLength)
527 return errors.New(errMsg)
528 }
529 }
530 return nil
531 }
532
533 func checkMinLength(field reflect.StructField, valueField reflect.Value, tag string) error {
534 if valueField.IsValid() {
535 minLength, err := strconv.Atoi(tag)
536 if err != nil {
537 return err
538 }
539 length := valueField.Len()
540 if valueField.Kind().String() == "string" {
541 length = strings.Count(valueField.String(), "") - 1
542 }
543 if minLength > length {
544 errMsg := fmt.Sprintf("The length of %s is %d which is less than %d", field.Name, length, minLength)
545 return errors.New(errMsg)
546 }
547 }
548 return nil
549 }
550
551 func checkMaximum(field reflect.StructField, valueField reflect.Value, tag string) error {
552 if valueField.IsValid() && valueField.String() != "" {
553 maximum, err := strconv.ParseFloat(tag, 64)
554 if err != nil {
555 return err
556 }
557 byt, _ := json.Marshal(valueField.Interface())
558 num, err := strconv.ParseFloat(string(byt), 64)
559 if err != nil {
560 return err
561 }
562 if maximum < num {
563 errMsg := fmt.Sprintf("The size of %s is %f which is greater than %f", field.Name, num, maximum)
564 return errors.New(errMsg)
565 }
566 }
567 return nil
568 }
569
570 func checkMinimum(field reflect.StructField, valueField reflect.Value, tag string) error {
571 if valueField.IsValid() && valueField.String() != "" {
572 minimum, err := strconv.ParseFloat(tag, 64)
573 if err != nil {
574 return err
575 }
576
577 byt, _ := json.Marshal(valueField.Interface())
578 num, err := strconv.ParseFloat(string(byt), 64)
579 if err != nil {
580 return err
581 }
582 if minimum > num {
583 errMsg := fmt.Sprintf("The size of %s is %f which is less than %f", field.Name, num, minimum)
584 return errors.New(errMsg)
585 }
586 }
587 return nil
588 }
589