Support binding for slice/array obj [Rewrite] (#2302)

Co-authored-by: thinkerou <thinkerou@gmail.com>
Co-authored-by: Bo-Yi Wu <appleboy.tw@gmail.com>
This commit is contained in:
wuhuizuo
2021-01-03 21:43:34 +08:00
committed by GitHub
parent a573ec6a37
commit 4bfae4c8c8
4 changed files with 142 additions and 11 deletions
+43 -9
View File
@@ -5,7 +5,9 @@
package binding
import (
"fmt"
"reflect"
"strings"
"sync"
"github.com/go-playground/validator/v10"
@@ -16,22 +18,54 @@ type defaultValidator struct {
validate *validator.Validate
}
type sliceValidateError []error
func (err sliceValidateError) Error() string {
var errMsgs []string
for i, e := range err {
if e == nil {
continue
}
errMsgs = append(errMsgs, fmt.Sprintf("[%d]: %s", i, e.Error()))
}
return strings.Join(errMsgs, "\n")
}
var _ StructValidator = &defaultValidator{}
// ValidateStruct receives any kind of type, but only performed struct or pointer to struct type.
func (v *defaultValidator) ValidateStruct(obj interface{}) error {
if obj == nil {
return nil
}
value := reflect.ValueOf(obj)
valueType := value.Kind()
if valueType == reflect.Ptr {
valueType = value.Elem().Kind()
}
if valueType == reflect.Struct {
v.lazyinit()
if err := v.validate.Struct(obj); err != nil {
return err
switch value.Kind() {
case reflect.Ptr:
return v.ValidateStruct(value.Elem().Interface())
case reflect.Struct:
return v.validateStruct(obj)
case reflect.Slice, reflect.Array:
count := value.Len()
validateRet := make(sliceValidateError, 0)
for i := 0; i < count; i++ {
if err := v.ValidateStruct(value.Index(i).Interface()); err != nil {
validateRet = append(validateRet, err)
}
}
if len(validateRet) == 0 {
return nil
}
return validateRet
default:
return nil
}
return nil
}
// validateStruct receives struct type
func (v *defaultValidator) validateStruct(obj interface{}) error {
v.lazyinit()
return v.validate.Struct(obj)
}
// Engine returns the underlying validator engine which powers the default