Tentar vincular o corpo à diferentes estruturas
Os métodos normais para vincular o corpo da requisição consumem a c.Request.Body
e não podem ser chamados várias vezes:
type formA struct {
Foo string `json:"foo" xml:"foo" binding:"required"`
}
type formB struct {
Bar string `json:"bar" xml:"bar" binding:"required"`
}
func SomeHandler(c *gin.Context) {
objA := formA{}
objB := formB{}
// Este c.ShouldBind consume o c.Request.Body e não pode ser reutilizado.
if errA := c.ShouldBind(&objA); errA == nil {
c.String(http.StatusOK, `the body should be formA`)
// Um erro sempre acontecerá por aqui porque c.Request.Body agora é EOF
} else if errB := c.ShouldBind(&objB); errB == nil {
c.String(http.StatusOK, `the body should be formB`)
} else {
...
}
}
Para isto, podes usar c.ShouldBindBodyWith
:
func SomeHandler(c *gin.Context) {
objA := formA{}
objB := formB{}
// Isto lê c.Request.Body e armazena o resultado no contexto.
if errA := c.ShouldBindBodyWith(&objA, binding.JSON); errA == nil {
c.String(http.StatusOK, `the body should be formA`)
// Neste momento, ela reutiliza o corpo armazenado no contexto.
} else if errB := c.ShouldBindBodyWith(&objB, binding.JSON); errB == nil {
c.String(http.StatusOK, `the body should be formB JSON`)
// E pode aceitar outros formatos
} else if errB2 := c.ShouldBindBodyWith(&objB, binding.XML); errB2 == nil {
c.String(http.StatusOK, `the body should be formB XML`)
} else {
...
}
}
c.ShouldBindBodyWidth
armazena o corpo no contexto antes da vinculação. Isto tem um ligeiro impacto no desempenho, então não deverias usar este método se estás bem para chamar a vinculação imediatamente.Esta funcionalidade é apenas necessário para alguns formatos –
JSON
,XML
,MsgPack
,ProtoBuf
. Para outros formatos,Query
,Form
,FormPost
,FormMultipart
, podem ser chamados pelac.ShouldBind()
várias vezes sem qualquer dado para o desempenho (consulte a #1341).