Pular para o conteúdo

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 pela c.ShouldBind() várias vezes sem qualquer dado para o desempenho (consulte a #1341).