Description
When gettig an error back from ShouldBind*
methods, im looking for a way to return to the user the correct field names
Looking at the ValidationErrors
and FieldError
structs i don't see the actual name of the query param
Is this a validator limitation or can this be solved by gin?
Side note - this part of the gin documentation is a bit lacking. it would be very beneficial to add an example about using ValidationErrors
, instead of just a normal go error
, when binding
How to reproduce
package main
import (
"errors"
"net/http"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
)
type queryTestStruct struct {
Param1 string `form:"othername" binding:"required"`
}
func main() {
r := gin.Default()
r.GET("/testQuery", func(c *gin.Context) {
var params queryTestStruct
err := c.ShouldBindQuery(¶ms)
if err != nil {
var ve validator.ValidationErrors
if errors.As(err, &ve) {
out := map[string]interface{}{}
for _, fe := range ve {
fieldName := fe.Field()
error := fe.Error()
out[fieldName] = error
}
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errors": out})
}
return
}
c.JSON(200, "No error")
})
r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}
Expectations
I expect to have some way to get from the FieldError
struct the actual expected query param name: othername
Actual result
$ curl --location 'localhost:8080/testQuery'
{
"errors": {
"Param1": "Key: 'queryTestStruct.Param1' Error:Field validation for 'Param1' failed on the 'required' tag"
}
}
Environment
- go version: 1.23
- gin version (or commit ref): v1.10.0
- operating system: Windows 11
Comment From: jerryyummy
you do not include the parameter, should use :curl -G "http://localhost:8080/testQuery" --data-urlencode "othername=your_value"
Comment From: OranShuster
you do not include the parameter, should use :curl -G "http://localhost:8080/testQuery" --data-urlencode "othername=your_value"
you are misunderstanding my question, im talking about query parameters error handling. obviously if ill send the parameter i won't get any error
Comment From: GenJi77JYXC
Maybe you can solve this problem using reflection
Here are some of my solutions
package main
import (
"errors"
"fmt"
"github.com/go-playground/validator/v10"
"net/http"
"reflect"
"github.com/gin-gonic/gin"
)
type queryTestStruct struct {
Param1 string `form:"othername" binding:"required"`
}
func main() {
r := gin.Default()
r.GET("/testQuery", func(c *gin.Context) {
var params queryTestStruct
err := c.ShouldBindQuery(¶ms)
if err != nil {
rType := reflect.TypeOf(new(queryTestStruct)).Elem()
var ve validator.ValidationErrors
if errors.As(err, &ve) {
out := map[string]interface{}{}
for _, fe := range ve {
fieldName := fe.Field()
param, ok := rType.FieldByName(fieldName)
if ok {
fmt.Println(param.Tag.Get("form"))// // Get param's correct field name
}
error := fe.Error()
out[fieldName] = error
out["tagName"] = param.Tag.Get("form")
}
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errors": out})
}
return
}
c.JSON(200, "No error")
})
r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}
Actual result
curl : {"errors":{"Param1":"Key: 'queryTestStruct.Param1' Error:Field validation for 'Param1' failed on the 'required' tag","tagName":"othername"}}
I used the tagName field to return the information you want
Comment From: jakubtomany
That's great there is a workaround with reflection, however, it would be great if gin binding package handles it correctly by registering a TagNameFunc
as mentioned here: https://github.com/go-playground/validator/issues/681#issuecomment-718356619