gin框架18--将 request body 绑定到不同的结构体中

gin框架18--将 request body 绑定到不同的结构体中

介绍

本文主要介绍如何将 request body 绑定到不同的结构体中,并加以案例说明。

案例

案例1: 使用 c.ShouldBind, 但不可重用

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

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{}
	// c.ShouldBind 使用了 c.Request.Body,不可重用。
	if errA := c.ShouldBind(&objA); errA == nil {
		c.String(http.StatusOK, `the body should be formA`)
		// 因为现在 c.Request.Body 是 EOF,所以这里会报错。
	} else if errB := c.ShouldBind(&objB); errB == nil {
		c.String(http.StatusOK, `the body should be formB`)
	} else {
		c.String(200, "not objA or objB")
	}
}

func main() {
	r := gin.Default()
	r.POST("/someHandler", SomeHandler)
	r.Run(":8080")
}

测试:

$ curl -H "Content-Type: application/json" -X POST http://127.0.0.1:8080/someHandler -d '{"foo":"v-foo"}'
the body should be formA

由于已经被 c.ShouldBind(&objA) 使用了,所以之后都无法正常匹配到
$ curl -H "Content-Type: application/json" -X POST http://127.0.0.1:8080/someHandler -d '{"bar":"v-bar"}'
not objA or objB

案例2: 使用 c.ShouldBindBodyWith 实现多次绑定

package main

import (
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"net/http"
)

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{}
	// 读取 c.Request.Body 并将结果存入上下文。
	if errA := c.ShouldBindBodyWith(&objA, binding.JSON); errA == nil {
		c.String(http.StatusOK, `the body should be formA`)
		// 这时, 复用存储在上下文中的 body。
	} else if errB := c.ShouldBindBodyWith(&objB, binding.JSON); errB == nil {
		c.String(http.StatusOK, `the body should be formB JSON`)
		// 可以接受其他格式
	} else if errB2 := c.ShouldBindBodyWith(&objB, binding.XML); errB2 == nil {
		c.String(http.StatusOK, `the body should be formB XML`)
	} else {
		c.String(200, "not objA or objB")
	}
}

func main() {
	r := gin.Default()
	r.POST("/someHandler", SomeHandler)
	r.Run(":8080")
}

测试:

$ curl -H "Content-Type: application/json" -X POST http://127.0.0.1:8080/someHandler -d '{"foo":"v-foo"}'
the body should be formA

$ curl -H "Content-Type: application/json" -X POST http://127.0.0.1:8080/someHandler -d '{"bar":"v-bar"}'
the body should be formB JSON

$ curl -H "Content-Type: application/json" -X POST http://127.0.0.1:8080/someHandler -d '{"cat":"v-cat\"}'
not objA or objB

c.ShouldBindBodyWith 会在绑定之前将 body 存储到上下文中。 这会对性能造成轻微影响,如果调用一次就能完成绑定的话,那就不要用这个方法。
只有某些格式需要此功能,如 JSON, XML, MsgPack, ProtoBuf。 对于其他格式, 如 Query, Form, FormPost, FormMultipart 可以多次调用 c.ShouldBind() 而不会造成任任何性能损失 (详见 #1341)。

说明

gin官方文档 将 request body 绑定到不同的结构体中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昕光xg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值