acabei de atualizar de v1.4.0 para v1.5.0 e acabamos com um erro interno do servidor na tag binding:"exists"
package main
import (
"github.com/gin-gonic/gin"
)
type User struct {
FirstName *string `json:"fn" binding:"exists"`
}
func main(){
router := gin.Default()
router.POST("/register", func(c *gin.Context) {
var user User
if err := c.BindJSON(&user); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"error": "first name cannot be empty",
})
return
}
})
router.Run(":8080")
}
return 400 with error message only if field FirstName is empty otherwise 200
2019/11/29 11:44:13 [Recovery] 2019/11/29 - 11:44:13 panic recovered:
Undefined validation function 'exists' on field 'FirstName'
/home/atif/go/src/github.com/go-playground/validator/cache.go:289 (0x7526b5)
(*Validate).parseFieldTagsRecursive: panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, current.tag, fieldName)))
/home/atif/go/src/github.com/go-playground/validator/cache.go:150 (0x751319)
(*Validate).extractStructCache: ctag, _ = v.parseFieldTagsRecursive(tag, fld.Name, "", false)
/home/atif/go/src/github.com/go-playground/validator/validator.go:37 (0x7577bd)
(*validate).validateStruct: cs = v.v.extractStructCache(current, typ.Name())
/home/atif/go/src/github.com/go-playground/validator/validator_instance.go:304 (0x75d706)
(*Validate).StructCtx: vd.validateStruct(ctx, top, val, val.Type(), vd.ns[0:0], vd.actualNs[0:0], nil)
/home/atif/go/src/github.com/go-playground/validator/validator_instance.go:277 (0x8eb6ed)
(*Validate).Struct: return v.StructCtx(context.Background(), s)
/home/atif/go/src/github.com/gin-gonic/gin/binding/default_validator.go:30 (0x8eb6b7)
(*defaultValidator).ValidateStruct: if err := v.validate.Struct(obj); err != nil {
/home/atif/go/src/github.com/gin-gonic/gin/binding/binding.go:113 (0x8ef50c)
validate: return Validator.ValidateStruct(obj)
/home/atif/go/src/github.com/gin-gonic/gin/binding/json.go:55 (0x8ef4c3)
decodeJSON: return validate(obj)
/home/atif/go/src/github.com/gin-gonic/gin/binding/json.go:37 (0x8ef337)
jsonBinding.Bind: return decodeJSON(req.Body, obj)
/home/atif/go/src/github.com/gin-gonic/gin/context.go:660 (0x8fc007)
(*Context).ShouldBindWith: return b.Bind(c.Request, obj)
/home/atif/go/src/github.com/gin-gonic/gin/context.go:603 (0x8fbfd1)
(*Context).MustBindWith: if err := c.ShouldBindWith(obj, b); err != nil {
/home/atif/go/src/github.com/gin-gonic/gin/context.go:566 (0xba6269)
(*Context).BindJSON: return c.MustBindWith(obj, binding.JSON)
/home/atif/go/src/gitlab.com/atif/project/handlers/user.go:32 (0xba622f)
(*Server).RegisterUser: if err := c.BindJSON(&u); err != nil {
/home/atif/go/src/github.com/gin-gonic/gin/context.go:147 (0x8f9859)
(*Context).Next: c.handlers[c.index](c)
/home/atif/go/src/gitlab.com/atif/project/middlewares/auth.go:32 (0xbb6963)
Auth.func1: c.Next()
/home/atif/go/src/github.com/gin-gonic/gin/context.go:147 (0x8f9859)
(*Context).Next: c.handlers[c.index](c)
/home/atif/go/src/github.com/gin-gonic/gin/recovery.go:83 (0x90d179)
RecoveryWithWriter.func1: c.Next()
/home/atif/go/src/github.com/gin-gonic/gin/context.go:147 (0x8f9859)
(*Context).Next: c.handlers[c.index](c)
/home/atif/go/src/github.com/gin-gonic/gin/logger.go:241 (0x90c2a0)
LoggerWithConfig.func1: c.Next()
/home/atif/go/src/github.com/gin-gonic/gin/context.go:147 (0x8f9859)
(*Context).Next: c.handlers[c.index](c)
/home/atif/go/src/github.com/gin-gonic/gin/gin.go:411 (0x90381c)
(*Engine).handleHTTPRequest: c.Next()
/home/atif/go/src/github.com/gin-gonic/gin/gin.go:369 (0x902f1d)
(*Engine).ServeHTTP: engine.handleHTTPRequest(c)
/usr/local/go/src/net/http/server.go:2774 (0x6cf5f7)
serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
/usr/local/go/src/net/http/server.go:1878 (0x6cb1e0)
(*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
/usr/local/go/src/runtime/asm_amd64.s:1337 (0x45f010)
goexit: BYTE $0x90 // NOP
Gin.v1.4.0 use validator.v8 para validação e gin.v1.5.0 use validator.v9;
Portanto, você pode definir a estrutura assim:
tipo User struct {
// Nome * string json:"fn" binding:"exists"
Nome * string json:"fn" binding:"required"
}
Obtive o resultado correto;
Mas required
não permite valor zero. ver # 491
Devemos usar *int
se quisermos permitir valor zero. Veja esta edição .
Comentários muito úteis
Gin.v1.4.0 use validator.v8 para validação e gin.v1.5.0 use validator.v9;
Portanto, você pode definir a estrutura assim:
tipo User struct {
// Nome * string
json:"fn" binding:"exists"
Nome * string
json:"fn" binding:"required"
}
Obtive o resultado correto;