Lewati ke konten

Mencoba bind body ke struct berbeda

Metode binding standar seperti c.ShouldBind mengonsumsi c.Request.Body, yang merupakan io.ReadCloser — setelah dibaca, tidak dapat dibaca lagi. Ini berarti Anda tidak dapat memanggil c.ShouldBind berkali-kali pada request yang sama untuk mencoba bentuk struct yang berbeda.

Untuk mengatasi ini, gunakan c.ShouldBindBodyWith. Metode ini membaca body sekali dan menyimpannya di context, memungkinkan binding berikutnya menggunakan kembali body yang sudah di-cache.

package main
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
type formA struct {
Foo string `json:"foo" xml:"foo" binding:"required"`
}
type formB struct {
Bar string `json:"bar" xml:"bar" binding:"required"`
}
func main() {
router := gin.Default()
router.POST("/bind", func(c *gin.Context) {
objA := formA{}
objB := formB{}
// This reads c.Request.Body and stores the result into the context.
if errA := c.ShouldBindBodyWith(&objA, binding.JSON); errA == nil {
c.JSON(http.StatusOK, gin.H{"message": "matched formA", "foo": objA.Foo})
return
}
// At this time, it reuses body stored in the context.
if errB := c.ShouldBindBodyWith(&objB, binding.JSON); errB == nil {
c.JSON(http.StatusOK, gin.H{"message": "matched formB", "bar": objB.Bar})
return
}
c.JSON(http.StatusBadRequest, gin.H{"error": "request body did not match any known format"})
})
router.Run(":8080")
}

Uji coba

Terminal window
# Body matches formA
curl -X POST http://localhost:8080/bind \
-H "Content-Type: application/json" \
-d '{"foo":"hello"}'
# Output: {"foo":"hello","message":"matched formA"}
# Body matches formB
curl -X POST http://localhost:8080/bind \
-H "Content-Type: application/json" \
-d '{"bar":"world"}'
# Output: {"bar":"world","message":"matched formB"}

Lihat juga