default_validator.go (2304B)
1 // Copyright 2017 Manu Martinez-Almeida. All rights reserved. 2 // Use of this source code is governed by a MIT style 3 // license that can be found in the LICENSE file. 4 5 package binding 6 7 import ( 8 "fmt" 9 "reflect" 10 "strings" 11 "sync" 12 13 "github.com/go-playground/validator/v10" 14 ) 15 16 type defaultValidator struct { 17 once sync.Once 18 validate *validator.Validate 19 } 20 21 type SliceValidationError []error 22 23 // Error concatenates all error elements in SliceValidationError into a single string separated by \n. 24 func (err SliceValidationError) Error() string { 25 n := len(err) 26 switch n { 27 case 0: 28 return "" 29 default: 30 var b strings.Builder 31 if err[0] != nil { 32 fmt.Fprintf(&b, "[%d]: %s", 0, err[0].Error()) 33 } 34 if n > 1 { 35 for i := 1; i < n; i++ { 36 if err[i] != nil { 37 b.WriteString("\n") 38 fmt.Fprintf(&b, "[%d]: %s", i, err[i].Error()) 39 } 40 } 41 } 42 return b.String() 43 } 44 } 45 46 var _ StructValidator = (*defaultValidator)(nil) 47 48 // ValidateStruct receives any kind of type, but only performed struct or pointer to struct type. 49 func (v *defaultValidator) ValidateStruct(obj any) error { 50 if obj == nil { 51 return nil 52 } 53 54 value := reflect.ValueOf(obj) 55 switch value.Kind() { 56 case reflect.Ptr: 57 return v.ValidateStruct(value.Elem().Interface()) 58 case reflect.Struct: 59 return v.validateStruct(obj) 60 case reflect.Slice, reflect.Array: 61 count := value.Len() 62 validateRet := make(SliceValidationError, 0) 63 for i := 0; i < count; i++ { 64 if err := v.ValidateStruct(value.Index(i).Interface()); err != nil { 65 validateRet = append(validateRet, err) 66 } 67 } 68 if len(validateRet) == 0 { 69 return nil 70 } 71 return validateRet 72 default: 73 return nil 74 } 75 } 76 77 // validateStruct receives struct type 78 func (v *defaultValidator) validateStruct(obj any) error { 79 v.lazyinit() 80 return v.validate.Struct(obj) 81 } 82 83 // Engine returns the underlying validator engine which powers the default 84 // Validator instance. This is useful if you want to register custom validations 85 // or struct level validations. See validator GoDoc for more info - 86 // https://pkg.go.dev/github.com/go-playground/validator/v10 87 func (v *defaultValidator) Engine() any { 88 v.lazyinit() 89 return v.validate 90 } 91 92 func (v *defaultValidator) lazyinit() { 93 v.once.Do(func() { 94 v.validate = validator.New() 95 v.validate.SetTagName("binding") 96 }) 97 }