Issue
So I have read the docs and I made my own custom validator to have custom error message formatting instead of the default which formats things that do not match the validation very ugly.
Example:
{"err":"Key: 'User.Email' Error:Field validation for 'Email' failed on the 'required' tag"}
So for that reason I have made my own, and I implemented the interface required for that, in Gin.
But however, even tho I have changed binding.Validator
my own validator is not really bound to binding.Validator
. I know I could make a global validator intead, but I want to have it into binding.Validator
package main
import (
"errors"
"fmt"
"log"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator"
)
type (
User struct {
Email string `validate:"required,min=3"`
}
Validator struct {
validate *validator.Validate
}
ErrorResponse struct {
Error bool
FailedField string
Tag string
Value string
}
)
func(c Validator) Engine() any {
return c.validate
}
func(c Validator) ValidateStruct(data any) error {
Error := &ErrorResponse{}
err := c.validate.Struct(data); if err != nil {
for _, err := range err.(validator.ValidationErrors) {
Error.FailedField = err.Field()
Error.Tag = err.Tag()
Error.Value = err.Value().(string)
Error.Error = true
// Do not return all errors joined at once
// bcs thats not a good practice
return errors.New(
fmt.Sprintf("[%s]: '%s' needs to implement '%s'",
err.Tag(),
err.Value().(string),
err.Tag()),
)
}
}
return nil
}
func main() {
app := gin.Default()
XValidator := &Validator{
validate: validator.New(),
}
binding.Validator = XValidator
vEngine, ok := binding.Validator.Engine().(*validator.Validate); if !ok {
fmt.Println(ok)
log.Fatal("Could not load validator engine")
}
// Global Error Handler
app.Use(func(c *gin.Context){
if len(c.Errors) > 0 {
c.JSON(403, gin.H{
"err": c.Errors[0],
})
}
c.Next()
})
app.GET("/", func(c *gin.Context) {
user := new(User)
user.Email = "e"
err := vEngine.Struct(user); if err != nil{
c.JSON(403, gin.H{
"err": err.Error(),
})
return
}
c.JSON(200, gin.H{
"message": "Hello World",
})
})
app.Run(":2000")
}