-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
How can I define custom error message? #559
Comments
@bakbuz take a look at the example of the translation for custom error message by locale https://github.com/go-playground/validator/blob/master/_examples/translations/main.go it's geared towards more general messages for each tag. If you need more custom messages I recommend creating your own messaging layer using all the information returned by each error, see the simple example for details https://github.com/go-playground/validator/blob/master/_examples/simple/main.go#L69 |
Thank you very much. |
Defining custom error messages are unneccessarily hard, i do not know why. |
I agree @bilalcaliskan! multiple steps to define which seems not ideal and then I still have to process/translate the errors that are returned from the library keeping a "global" translation instance around. I don't understand why the libary can't handle the translation internally before return an error. ie: https://github.com/go-playground/validator/blob/master/_examples/translations/main.go#L126. 🤯 |
A guy helped me on stackoverflow to easily create my custom error messages by watching the current tag. type ApiError struct {
Param string
Message string
}
type User struct {
FirstName string `binding:"required"`
LastName string `binding:"required"`
Age uint8 `binding:"gte=0,lte=130"`
Email string `binding:"required,email"`
FavouriteColor string `binding:"iscolor"`
}
func msgForTag(fe validator.FieldError) string {
switch fe.Tag() {
case "required":
return "This field is required"
case "email":
return "Invalid email"
}
return fe.Error() // default error
}
// Gin handler in my case
func handler(c *gin.Context) {
var u User
if err := c.ShouldBindQuery(&u); err == nil {
c.JSON(http.StatusOK, gin.H{"message": "Good Job"})
} else {
var ve validator.ValidationErrors
if errors.As(err, &ve) {
out := make([]ApiError, len(ve))
for i, fe := range ve {
out[i] = ApiError{fe.Field(), msgForTag(fe)}
}
c.JSON(http.StatusBadRequest, gin.H{"errors": out})
}
return
}
} And the output will be: {
"errors": [
{
"Param": "FirstName",
"Message": "This field is required"
},
{
"Param": "LastName",
"Message": "This field is required"
},
{
"Param": "Email",
"Message": "Invalid email"
},
{
"Param": "FavouriteColor",
"Message": "Key: 'User.FavouriteColor' Error:Field validation for 'FavouriteColor' failed on the 'iscolor' tag"
}
]
} |
@johngtrs John, i'm trying to run your example and getting an error
my guess validator API changed? how do you do it now? My bad, for some reason go get installed v9 (I do have quite old project and looks like someone already tried to use validator before) after code clean up + go mod tidy i'm no longer seeing an error |
Is there any solution for custom message for other type different than 'string'. For example int, uint, float, float64 etc ...??? |
You might find this useful. |
Fiber has an example on how to do this: https://docs.gofiber.io/guide/validation/ |
In my echo app, I used the similar pattern: func BindAndValidate(c echo.Context, req interface{}) error {
if err := c.Bind(req); err != nil {
return err
}
if err := c.Validate(req); err != nil {
if _, ok := err.(*validator.InvalidValidationError); ok {
log.Error(err)
return errors.New("Something went wrong. Please try again later.")
}
var verr validationErrors
for _, err := range err.(validator.ValidationErrors) {
var e error
switch err.Tag() {
case "required":
e = fmt.Errorf("Field '%s' cannot be blank", err.Field())
case "email":
e = fmt.Errorf("Field '%s' must be a valid email address", err.Field())
case "eth_addr":
e = fmt.Errorf("Field '%s' must be a valid Ethereum address", err.Field())
case "len":
e = fmt.Errorf("Field '%s' must be exactly %v characters long", err.Field(), err.Param())
default:
e = fmt.Errorf("Field '%s': '%v' must satisfy '%s' '%v' criteria", err.Field(), err.Value(), err.Tag(), err.Param())
}
verr = append(verr, e)
}
return verr
}
return nil
}
type validationErrors []error
func (ve validationErrors) Error() string {
buff := bytes.NewBufferString("")
for i := 0; i < len(ve); i++ {
buff.WriteString(ve[i].Error())
buff.WriteString("\n")
}
return strings.TrimSpace(buff.String())
} |
Thanks everybody |
func InitReqDataValidationTranslation() {
} Here is my code for custom message for min tag. Thanks in Advance. |
This seems way harder than it should be. It covers the advanced translation case, but it doesn't provide an easy way to do the simple use case like most other validation libraries provide. This should be as simple as: type MyStruct struct {
Name string `validate:"required",validateMsg:"A name is required"`
ADate civil.Date `validate:"customCivilDate",validateMsg:"Must be in the format YYYY-MM-DD"`
} My desired behavior is for |
It is puzzling how difficult this is by default. Really. This is my attempt to make this a bit less painful. This is an untested snippet of a translator that would read from the enLocale := en.New()
translator, _ := ut.New(enLocale, enLocale).GetTranslator("en")
validate.RegisterTranslation("msg", translator,
func(ut ut.Translator) error {
return ut.Add("msg", "{0}", true)
},
func(ut ut.Translator, fe validator.FieldError) string {
s, _ := ut.T("msg")
return s
},
) |
How can I define custom error message? I don't want to make a detailed explanation. I just want to make a brief statement.
For example:
The text was updated successfully, but these errors were encountered: