-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvalidatorExtract.go
More file actions
95 lines (82 loc) · 3.09 KB
/
validatorExtract.go
File metadata and controls
95 lines (82 loc) · 3.09 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
package validator
import (
"fmt"
"reflect"
"strings"
"github.com/siherrmann/validator/helper"
"github.com/siherrmann/validator/model"
)
// GetValidationsFromStruct extracts validation rules from a struct based on the provided tag type.
// It iterates over the struct fields, checks for the specified tag type, and constructs Validation.
func GetValidationsFromStruct(in any, tagType string) ([]model.Validation, error) {
err := helper.CheckValidPointerToStruct(in)
if err != nil {
return nil, err
}
validations := []model.Validation{}
structFull := reflect.ValueOf(in).Elem()
for i := 0; i < structFull.Type().NumField(); i++ {
field := structFull.Field(i)
fieldType := structFull.Type().Field(i)
validation, err := GetValidationFromStructField(tagType, field, fieldType)
if err != nil {
return nil, err
} else if validation == nil {
continue
}
if len(validation.Requirement) > 0 {
validations = append(validations, *validation)
}
}
return validations, nil
}
// GetValidationFromStructField extracts validation rules from a struct field based on the provided tag type.
// It checks the field's tag for the specified tag type and constructs a Validation object.
// If no json tag is found, it uses the field name as the key.
func GetValidationFromStructField(tagType string, fieldValue reflect.Value, fieldType reflect.StructField) (*model.Validation, error) {
validation := &model.Validation{}
validation.Key = fieldType.Name
if len(fieldType.Tag.Get("json")) > 0 {
jsonKey := fieldType.Tag.Get("json")
// Split on comma to handle omitempty and other options
jsonKey = strings.Split(jsonKey, ",")[0]
if jsonKey != "-" {
validation.Key = jsonKey
}
}
validation.Type = model.ReflectKindToValidatorType(fieldValue.Type().Kind())
validation.Requirement = "-"
tagIndex := 0
tagSplit := strings.Split(fieldType.Tag.Get(string(tagType)), ", ")
if len(tagSplit) > tagIndex {
// Ignore if tag is empty, we do not want to validate this field at all
if len(tagSplit[tagIndex]) <= 3 && tagSplit[tagIndex] != "-" {
return nil, nil
}
validation.Requirement = tagSplit[tagIndex]
tagIndex++
}
if len(tagSplit) > tagIndex {
var err error
validation.Groups, err = model.GetGroups(tagSplit[tagIndex])
if err != nil {
return nil, fmt.Errorf("error extracting group: %v", err)
}
}
if helper.IsArrayOfStruct(fieldValue.Interface()) {
innerStruct := reflect.New(fieldValue.Type().Elem()).Interface()
innerValidation, err := GetValidationsFromStruct(innerStruct, string(tagType))
if err != nil {
return nil, fmt.Errorf("error getting inner validation from array: %v", err)
}
validation.InnerValidation = append(validation.InnerValidation, innerValidation...)
} else if helper.IsStruct(fieldValue.Interface()) {
innerStruct := reflect.New(fieldValue.Type()).Interface()
innerValidation, err := GetValidationsFromStruct(innerStruct, string(tagType))
if err != nil {
return nil, fmt.Errorf("error getting inner validation from struct: %v", err)
}
validation.InnerValidation = append(validation.InnerValidation, innerValidation...)
}
return validation, nil
}