1 package main
2
3 import (
4 "encoding/json"
5 "fmt"
6 "reflect"
7 "strings"
8
9 "github.com/go-playground/validator/v10"
10 )
11
12 type validationError struct {
13 Namespace string `json:"namespace"`
14 Field string `json:"field"`
15 StructNamespace string `json:"structNamespace"`
16 StructField string `json:"structField"`
17 Tag string `json:"tag"`
18 ActualTag string `json:"actualTag"`
19 Kind string `json:"kind"`
20 Type string `json:"type"`
21 Value string `json:"value"`
22 Param string `json:"param"`
23 Message string `json:"message"`
24 }
25
26 type Gender uint
27
28 const (
29 Male Gender = iota + 1
30 Female
31 Intersex
32 )
33
34 func (gender Gender) String() string {
35 terms := []string{"Male", "Female", "Intersex"}
36 if gender < Male || gender > Intersex {
37 return "unknown"
38 }
39 return terms[gender]
40 }
41
42
43 type User struct {
44 FirstName string `json:"fname"`
45 LastName string `json:"lname"`
46 Age uint8 `validate:"gte=0,lte=130"`
47 Email string `json:"e-mail" validate:"required,email"`
48 FavouriteColor string `validate:"hexcolor|rgb|rgba"`
49 Addresses []*Address `validate:"required,dive,required"`
50 Gender Gender `json:"gender" validate:"required,gender_custom_validation"`
51 }
52
53
54 type Address struct {
55 Street string `validate:"required"`
56 City string `validate:"required"`
57 Planet string `validate:"required"`
58 Phone string `validate:"required"`
59 }
60
61
62 var validate *validator.Validate
63
64 func main() {
65
66 validate = validator.New()
67
68
69 validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
70 name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
71 if name == "-" {
72 return ""
73 }
74 return name
75 })
76
77
78
79
80 validate.RegisterStructValidation(UserStructLevelValidation, User{})
81
82
83
84 err := validate.RegisterValidation("gender_custom_validation", func(fl validator.FieldLevel) bool {
85 value := fl.Field().Interface().(Gender)
86 return value.String() != "unknown"
87 })
88 if err != nil {
89 fmt.Println(err)
90 return
91 }
92
93
94 address := &Address{
95 Street: "Eavesdown Docks",
96 Planet: "Persphone",
97 Phone: "none",
98 City: "Unknown",
99 }
100
101 user := &User{
102 FirstName: "",
103 LastName: "",
104 Age: 45,
105 Email: "Badger.Smith@gmail",
106 FavouriteColor: "#000",
107 Addresses: []*Address{address},
108 }
109
110
111 err = validate.Struct(user)
112 if err != nil {
113
114
115
116
117 if _, ok := err.(*validator.InvalidValidationError); ok {
118 fmt.Println(err)
119 return
120 }
121
122 for _, err := range err.(validator.ValidationErrors) {
123 e := validationError{
124 Namespace: err.Namespace(),
125 Field: err.Field(),
126 StructNamespace: err.StructNamespace(),
127 StructField: err.StructField(),
128 Tag: err.Tag(),
129 ActualTag: err.ActualTag(),
130 Kind: fmt.Sprintf("%v", err.Kind()),
131 Type: fmt.Sprintf("%v", err.Type()),
132 Value: fmt.Sprintf("%v", err.Value()),
133 Param: err.Param(),
134 Message: err.Error(),
135 }
136
137 indent, err := json.MarshalIndent(e, "", " ")
138 if err != nil {
139 fmt.Println(err)
140 panic(err)
141 }
142
143 fmt.Println(string(indent))
144 }
145
146
147 return
148 }
149
150
151 }
152
153
154
155
156
157
158
159
160
161
162 func UserStructLevelValidation(sl validator.StructLevel) {
163
164 user := sl.Current().Interface().(User)
165
166 if len(user.FirstName) == 0 && len(user.LastName) == 0 {
167 sl.ReportError(user.FirstName, "fname", "FirstName", "fnameorlname", "")
168 sl.ReportError(user.LastName, "lname", "LastName", "fnameorlname", "")
169 }
170
171
172 }
173
View as plain text