github.com/sandwich-go/boost@v1.3.29/validator/validator.go (about) 1 package validator 2 3 import ( 4 "context" 5 ut "github.com/go-playground/universal-translator" 6 validator2 "github.com/go-playground/validator/v10" 7 "github.com/sandwich-go/boost/xerror" 8 "reflect" 9 ) 10 11 type ( 12 // FieldError contains all functions to get error details 13 FieldError = validator2.FieldError 14 // FieldLevel contains all the information and helper functions 15 // to validate a field 16 FieldLevel = validator2.FieldLevel 17 // StructLevel contains all the information and helper functions 18 // to validate a struct 19 StructLevel = validator2.StructLevel 20 // TagNameFunc allows for adding of a custom tag name parser 21 TagNameFunc = validator2.TagNameFunc 22 // Func accepts a context.Context and FieldLevel interface for all 23 // validation needs. The return value should be true when validation succeeds. 24 Func = validator2.FuncCtx 25 // StructLevelFunc accepts all values needed for struct level validation 26 // but also allows passing of contextual validation information via context.Context. 27 StructLevelFunc = validator2.StructLevelFuncCtx 28 // CustomTypeFunc allows for overriding or adding custom field type handler functions 29 // field = field value of the type to return a value to be validated 30 // example Valuer from sql drive see https://golang.org/src/database/sql/driver/types.go?s=1210:1293#L29 31 CustomTypeFunc = validator2.CustomTypeFunc 32 // RegisterTranslationsFunc allows for registering of translations 33 // for a 'ut.Translator' for use within the 'TranslationFunc' 34 RegisterTranslationsFunc = validator2.RegisterTranslationsFunc 35 // TranslationFunc is the function type used to register or override 36 // custom translations 37 TranslationFunc = validator2.TranslationFunc 38 // FilterFunc is the type used to filter fields using 39 // StructFiltered(...) function. 40 // returning true results in the field being filtered/skiped from 41 // validation 42 FilterFunc = validator2.FilterFunc 43 44 // ValidationErrors is an array of FieldError's 45 // for use in custom error messages post validation. 46 ValidationErrors = validator2.ValidationErrors 47 ) 48 49 // Validator validator 50 type Validator interface { 51 // SetTagName allows for changing of the default tag name of Validator 52 SetTagName(name string) 53 54 // ValidateMap validates a map using a map of validation rules and allows passing of contextual 55 // validation validation information via context.Context. 56 ValidateMap(ctx context.Context, data map[string]interface{}, rules map[string]interface{}) map[string]interface{} 57 58 // RegisterTagNameFunc registers a function to get alternate names for StructFields. 59 // 60 // eg. to use the names which have been specified for JSON representations of structs, rather than normal Go field names: 61 // 62 // validate.RegisterTagNameFunc(func(fld reflect.StructField) string { 63 // name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] 64 // // skip if tag key says it should be ignored 65 // if name == "-" { 66 // return "" 67 // } 68 // return name 69 // }) 70 RegisterTagNameFunc(fn TagNameFunc) 71 72 // RegisterAlias registers a mapping of a single validation tag that 73 // defines a common or complex set of validation(s) to simplify adding validation 74 // to structs. 75 // 76 // NOTE: this function is not thread-safe it is intended that these all be registered prior to any validation 77 RegisterAlias(alias, tags string) 78 79 // RegisterValidation adds a validation with the given tag 80 // allowing context.Context validation support. 81 // 82 // NOTES: 83 // - if the key already exists, the previous validation function will be replaced. 84 // - this method is not thread-safe it is intended that these all be registered prior to any validation 85 RegisterValidation(tag string, fn Func, callValidationEvenIfNull ...bool) error 86 87 // RegisterStructValidation registers a StructLevelFunc against a number of types and allows passing 88 // of contextual validation information via context.Context. 89 // 90 // NOTE: 91 // - this method is not thread-safe it is intended that these all be registered prior to any validation 92 RegisterStructValidation(fn StructLevelFunc, types ...interface{}) 93 94 // RegisterStructValidationMapRules registers validate map rules. 95 // Be aware that map validation rules supersede those defined on a/the struct if present. 96 // 97 // NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation 98 RegisterStructValidationMapRules(rules map[string]string, types ...interface{}) 99 100 // RegisterCustomTypeFunc registers a CustomTypeFunc against a number of types 101 // 102 // NOTE: this method is not thread-safe it is intended that these all be registered prior to any validation 103 RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{}) 104 105 // RegisterTranslation registers translations against the provided tag. 106 RegisterTranslation(tag string, trans ut.Translator, registerFn RegisterTranslationsFunc, translationFn TranslationFunc) error 107 108 // Struct validates a structs exposed fields, and automatically validates nested structs, unless otherwise specified 109 // and also allows passing of context.Context for contextual validation information. 110 // 111 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise. 112 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors. 113 Struct(ctx context.Context, s interface{}) error 114 115 // StructFiltered validates a structs exposed fields, that pass the FilterFunc check and automatically validates 116 // nested structs, unless otherwise specified and also allows passing of contextual validation information via 117 // context.Context 118 // 119 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise. 120 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors. 121 StructFiltered(ctx context.Context, s interface{}, fn FilterFunc) error 122 123 // StructPartial validates the fields passed in only, ignoring all others and allows passing of contextual 124 // validation validation information via context.Context 125 // Fields may be provided in a namespaced fashion relative to the struct provided 126 // eg. NestedStruct.Field or NestedArrayField[0].Struct.Name 127 // 128 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise. 129 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors. 130 StructPartial(ctx context.Context, s interface{}, fields ...string) error 131 132 // StructExcept validates all fields except the ones passed in and allows passing of contextual 133 // validation validation information via context.Context 134 // Fields may be provided in a namespaced fashion relative to the struct provided 135 // i.e. NestedStruct.Field or NestedArrayField[0].Struct.Name 136 // 137 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise. 138 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors. 139 StructExcept(ctx context.Context, s interface{}, fields ...string) error 140 141 // Var validates a single variable using tag style validation and allows passing of contextual 142 // validation validation information via context.Context. 143 // eg. 144 // var i int 145 // validate.Var(i, "gt=1,lt=10") 146 // 147 // WARNING: a struct can be passed for validation eg. time.Time is a struct or 148 // if you have a custom type and have registered a custom type handler, so must 149 // allow it; however unforeseen validations will occur if trying to validate a 150 // struct that is meant to be passed to 'validate.Struct' 151 // 152 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise. 153 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors. 154 // validate Array, Slice and maps fields which may contain more than one error 155 Var(ctx context.Context, val interface{}, tag string) error 156 157 // VarWithValue validates a single variable, against another variable/field's value using tag style validation and 158 // allows passing of contextual validation validation information via context.Context. 159 // eg. 160 // s1 := "abcd" 161 // s2 := "abcd" 162 // validate.VarWithValue(s1, s2, "eqcsfield") // returns true 163 // 164 // WARNING: a struct can be passed for validation eg. time.Time is a struct or 165 // if you have a custom type and have registered a custom type handler, so must 166 // allow it; however unforeseen validations will occur if trying to validate a 167 // struct that is meant to be passed to 'validate.Struct' 168 // 169 // It returns InvalidValidationError for bad values passed in and nil or ValidationErrors as error otherwise. 170 // You will need to assert the error if it's not nil eg. err.(validator.ValidationErrors) to access the array of errors. 171 // validate Array, Slice and maps fields which may contain more than one error 172 VarWithValue(ctx context.Context, field interface{}, other interface{}, tag string) error 173 } 174 175 var ( 176 Default = New() 177 Validate = Default 178 ) 179 180 type validate struct { 181 v *validator2.Validate 182 } 183 184 // New returns a new Validator with sane defaults. 185 // Validator is designed to be thread-safe and used as a singleton instance. 186 // It caches information about your struct and validations, 187 // in essence only parsing your validation tags once per struct type. 188 // Using multiple instances neglects the benefit of caching. 189 func New() Validator { 190 return &validate{v: validator2.New()} 191 } 192 193 func (v *validate) SetTagName(name string) { v.v.SetTagName(name) } 194 func (v *validate) RegisterTagNameFunc(fn TagNameFunc) { v.v.RegisterTagNameFunc(fn) } 195 func (v *validate) RegisterAlias(alias, tags string) { v.v.RegisterAlias(alias, tags) } 196 func (v *validate) RegisterValidation(tag string, fn Func, callValidationEvenIfNull ...bool) error { 197 return v.v.RegisterValidationCtx(tag, fn, callValidationEvenIfNull...) 198 } 199 func (v *validate) RegisterStructValidation(fn StructLevelFunc, types ...interface{}) { 200 v.v.RegisterStructValidationCtx(fn, types...) 201 } 202 func (v *validate) RegisterStructValidationMapRules(rules map[string]string, types ...interface{}) { 203 v.v.RegisterStructValidationMapRules(rules, types...) 204 } 205 func (v *validate) RegisterCustomTypeFunc(fn CustomTypeFunc, types ...interface{}) { 206 v.v.RegisterCustomTypeFunc(fn, types...) 207 } 208 func (v *validate) RegisterTranslation(tag string, trans ut.Translator, registerFn RegisterTranslationsFunc, translationFn TranslationFunc) error { 209 return v.v.RegisterTranslation(tag, trans, registerFn, translationFn) 210 } 211 func (v *validate) ValidateMap(ctx context.Context, data map[string]interface{}, rules map[string]interface{}) map[string]interface{} { 212 return v.v.ValidateMapCtx(ctx, data, rules) 213 } 214 func (v *validate) Var(ctx context.Context, val interface{}, tag string) (err error) { 215 defer func() { 216 if r := recover(); r != nil { 217 err = xerror.NewText("validate panic with val: %v, tag: %s, reason: %v", val, tag, r) 218 } 219 }() 220 err = v.v.VarCtx(ctx, val, tag) 221 return 222 } 223 func (v *validate) Struct(ctx context.Context, s interface{}) (err error) { 224 defer func() { 225 if r := recover(); r != nil { 226 err = xerror.NewText("validate panic with struct: %s, reason: %v", reflect.TypeOf(s).String(), r) 227 } 228 }() 229 err = v.v.StructCtx(ctx, s) 230 return 231 } 232 func (v *validate) StructFiltered(ctx context.Context, s interface{}, fn FilterFunc) error { 233 return v.v.StructFilteredCtx(ctx, s, fn) 234 } 235 func (v *validate) StructPartial(ctx context.Context, s interface{}, fields ...string) error { 236 return v.v.StructPartialCtx(ctx, s, fields...) 237 } 238 func (v *validate) StructExcept(ctx context.Context, s interface{}, fields ...string) error { 239 return v.v.StructExceptCtx(ctx, s, fields...) 240 } 241 func (v *validate) VarWithValue(ctx context.Context, field interface{}, other interface{}, tag string) error { 242 return v.v.VarWithValueCtx(ctx, field, other, tag) 243 }