You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The parameter of the RegisterValidation function is a validation function that returns a Boolean value. If we want to customize the error message, we have to register a translation function, which is too much trouble.
Our verification function may return an error for many reasons, so the error message should also be different, but only based on the returned boolean value, we cannot determine what caused the verification failure, so the error message of the translation function is only One kind.
Why can't you register a check function that returns error directly?
Just like the following.
type Func=func(fl FieldLevel) error
func (v *Validate) RegisterValidation(tag string, fn Func, callValidationEvenIfNull ...bool) error {
}
Reacted by William, York, Cornel, David Pennington, 9tec7, Jacob Hochstetler, xlotusx, Henry Sequeda González, Teofanus Gary, Vitaliy F. and 22 more
Only based on the boolean value returned by the validation function, we cannot determine what caused the validation failure, so customizing the error message will be very troublesome
@deankarn
I simply made some changes to the "validator", which is currently supported and used in my own project.
My implementation is like this:
Provides two RegisterValidation functions, the first parameter type is still "type Func=func(fl FieldLevel) boolean",
The parameter type of the second function becomes "type Func=func(fl FieldLevel) error".
When verifying, you only need to determine which type of verification function is.
I think it's possible to implement this without a breaking change, though it'll be ugly with some bits of code purely dedicated to backwards compatibility. We'd have to put a new registration mechanism with new names next to the current one, and turn the current one into a proxy:
Of course, it would still be a pretty big change to the deeper architecture of the library: all baked-in validators would need to be wrapped, all code which calls the validators needs to call them by the new signature, and I don't know the codebase well enough to tell if more things than that need to be changed.
Would the maintainer(s) of this project be on board with this solution? If yes, would you appreciate me familiarising myself with the codebase and cooking up a PR for this, or would you prefer to implement this yourself?
Reacted by Maxime Lacroix, Iván Sánchez and abdulrahmansaja2002
To reiterate, because some comments here seem to think this is about purely customising the error message, but it is not. It's about being able to return an error message that gives deeper reasons why a custom validation failed. That reason might change according to the intricate and particular contents of the field.
Imagine for example a struct field that is a custom string type, and it is meant to conform to a particular grammar that I've created elsewhere in my code. What I want is to return specific, helpful error messages when that parsing fails. The message will change according to the specifics of the input string, so can't be solved with static custom message tags, or with the current "translation" workaround.
Here's a limited v10 workaround for single field validation. It doesn't work for cross field or cross struct validations, but might work if you just need to, say, validate syntax on a string field. It does require executing the custom validation twice: once to induce a FieldError and again to get an actual error back when processing FieldErrors.
This isn't production-ready code, but just to give the flavor.
func RealValidateFoo(foo string, param string) error {
// perform syntax validation on foo
}
err = validate.RegisterValidation("foo", func(fl validator.FieldLevel) bool {
return RealValidateFoo(fl.Field().String(), fl.Param()) == nil
})
// later on, when iterating over validation errors
switch err := err.(type) {
case validator.ValidationErrors:
for _, fieldErr := range err {
errMsg := fieldErr.Error()
switch fieldErr.Tag() {
case "foo":
customErr := RealValidateFoo(fmt.Sprint(fieldErr.Value()), fieldErr.Param())
if customErr != nil {
errMsg = customErr.Error()
}
// check other custom validations
}
fmt.Println(errMsg)
}
...
}
i'm also interested on this. Currently was able to workaround this with
func (v *Validator) validateExpr(ctx context.Context, fl validator.FieldLevel) bool {
expr := fl.Field().String()
_, err := doThing(ctx, expr)
if err != nil {
type reporter interface {
ReportError(field interface{}, fieldName, structFieldName string, tag, param string)
}
//
if r, ok := fl.(reporter); ok {
r.ReportError(fl.Field(), fl.FieldName(), fl.StructFieldName(), fl.GetTag(), err.Error())
// we don't return false here as we use alternative way to report the error
return true
}
return false
}
return true
}
But the solution is hackish. Actually just an ability to set Param in validator.FieldLevel will be already good enough.
Activity
1379 commentedon Sep 28, 2020
Only based on the boolean value returned by the validation function, we cannot determine what caused the validation failure, so customizing the error message will be very troublesome
deankarn commentedon Oct 17, 2020
@1379 sounds like a great enhancement for the next version of the lib, but unfortunately right now is a breaking change.
1379 commentedon Oct 17, 2020
@deankarn
I simply made some changes to the "validator", which is currently supported and used in my own project.
My implementation is like this:
Provides two RegisterValidation functions, the first parameter type is still "type Func=func(fl FieldLevel) boolean",
The parameter type of the second function becomes "type Func=func(fl FieldLevel) error".
When verifying, you only need to determine which type of verification function is.
pwli0755 commentedon Oct 20, 2020
Same need
kke commentedon Nov 18, 2020
The custom validation error messages from
sl.ReportError()are a bit silly too:==>
If it was not from a tag, but a custom StructValidation , it should say something like:
kevin2027 commentedon Sep 18, 2021
here is a way to fix it #837
pbikki commentedon Apr 13, 2023
same need. especially for
sl.ReportError()on struct validation to include custom error messages to userjoostvdhoff commentedon Sep 4, 2024
I think it's possible to implement this without a breaking change, though it'll be ugly with some bits of code purely dedicated to backwards compatibility. We'd have to put a new registration mechanism with new names next to the current one, and turn the current one into a proxy:
Of course, it would still be a pretty big change to the deeper architecture of the library: all baked-in validators would need to be wrapped, all code which calls the validators needs to call them by the new signature, and I don't know the codebase well enough to tell if more things than that need to be changed.
Would the maintainer(s) of this project be on board with this solution? If yes, would you appreciate me familiarising myself with the codebase and cooking up a PR for this, or would you prefer to implement this yourself?
ezk84 commentedon Oct 30, 2024
Need this also.
To reiterate, because some comments here seem to think this is about purely customising the error message, but it is not. It's about being able to return an error message that gives deeper reasons why a custom validation failed. That reason might change according to the intricate and particular contents of the field.
Imagine for example a struct field that is a custom string type, and it is meant to conform to a particular grammar that I've created elsewhere in my code. What I want is to return specific, helpful error messages when that parsing fails. The message will change according to the specifics of the input string, so can't be solved with static custom message tags, or with the current "translation" workaround.
+1 on @joostvdhoff's proposal from me!
mbarnes commentedon Mar 12, 2025
Here's a limited v10 workaround for single field validation. It doesn't work for cross field or cross struct validations, but might work if you just need to, say, validate syntax on a string field. It does require executing the custom validation twice: once to induce a
FieldErrorand again to get an actualerrorback when processingFieldErrors.This isn't production-ready code, but just to give the flavor.
dumindu commentedon Jun 25, 2025
Please also support forwarding parameters in aliases. For example,
So, can define different messages for the same validator.
avasenin commentedon Jul 7, 2025
i'm also interested on this. Currently was able to workaround this with
But the solution is hackish. Actually just an ability to set Param in validator.FieldLevel will be already good enough.