-
Notifications
You must be signed in to change notification settings - Fork 8.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Export struct sliceValidateError to allow error casting #2777
Conversation
SliceValidationError
@appleboy @thinkerou Can we get this merged? I also found myself needing this. Without it, I have to iterate over slices manually, so that I can access the individual validation errors. |
@kszafran I strongly support the proposal of this function and hope it can be integrated into the trunk.
…------------------ Original ------------------
From: kszafran ***@***.***>
Date: Fri,Aug 6,2021 5:35 PM
To: gin-gonic/gin ***@***.***>
Cc: heige ***@***.***>, Comment ***@***.***>
Subject: Re: [gin-gonic/gin] Export struct sliceValidateError to allow error casting (#2777)
@appleboy @thinkerou Can we get this merged? I also found myself needing this. Without it, I have to iterate over slices manually, so that I can access the individual validation errors.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
|
@appleboy @thinkerou Any chance to get this merged ? Thanks ! |
need @thinkerou's approval. |
I would actually advice against merging this. I have an alternative idea and could contribute a PR. I'm playing with it right now, validator has a method called I'm also adding a feature allowing configuring validation tags for map/slice types. |
Here is a proof of concept. Registering type tags is similar to registering struct-level validators: var typeTags = make(map[reflect.Type]string)
// RegisterTypeTag registers a validator tag for a map or slice type. For example:
// infra.RegisterMapTag(api.MyMap{}, "gt=3,dive")
// where api.MyMap is a map type, e.g.
// type MyMap map[string]int
// If you register a tag, you have to include "dive" to validate map/slice elements.
func RegisterTypeTag(typ interface{}, tag string) {
// TODO panic if the type is not one of: Slice, Array, Map
typeTags[reflect.TypeOf(typ)] = tag
}
type defaultValidator struct {
once sync.Once
validate *validator.Validate
}
var _ binding.StructValidator = &defaultValidator{}
func (v *defaultValidator) ValidateStruct(obj interface{}) error {
if obj == nil {
return nil
}
value := reflect.ValueOf(obj)
switch value.Kind() {
case reflect.Ptr:
return v.ValidateStruct(value.Elem().Interface())
case reflect.Struct:
return v.validateStruct(obj)
case reflect.Slice, reflect.Array, reflect.Map:
if tag, ok := typeTags[value.Type()]; ok {
return v.validateVar(obj, tag)
} else {
return v.validateVar(obj, "dive")
}
default:
return nil
}
}
func (v *defaultValidator) validateStruct(obj interface{}) error {
v.lazyinit()
return v.validate.Struct(obj)
}
func (v *defaultValidator) validateVar(obj interface{}, tag string) error {
v.lazyinit()
return v.validate.Var(obj, tag)
}
func (v *defaultValidator) Engine() interface{} {
v.lazyinit()
return v.validate
}
func (v *defaultValidator) lazyinit() {
v.once.Do(func() {
v.validate = validator.New()
v.validate.SetTagName("binding")
})
} The benefits are:
binding.RegisterTypeTag(MyMap{}, "dive,keys,gt=5,endkeys,dive") This allows you to validate top-level map keys (not possible currently), as well as top-level slices (also not possible): binding.RegisterTypeTag(MySlice{}, "gt=4,dive") If we merge this PR and export |
I can create a PR tomorrow. I can also see if I could implement contextual validation: #2741 |
Here you go: #2877 @appleboy @thinkerou |
I have reworked my implementation. It's now more similar to the existing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hbvjhbjhbh
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
… as (gin-gonic#2777) SliceValidationError Co-authored-by: Emeric de Bernis <emeric.debernis@adevinta.com>
This PR allows to cast error returned by ShouldBindWith functions when input parameter is a slice.