gin 三.请求数据的映射

基础解释

  1. 解释: 例如后端获取调用方参数,通常会使用一个结构体,或一个变量来接收,调用方传递的数据会自动映射到该变量上,而不是通过request去手动获取,怎么映射
  2. 目前Gin⽀持JSON、XML、YAML和标准表单值的绑定。就是根据Body数据类型,将数据赋值到指定的结构体变量中 (类似于序列化和反序列化)
  3. go提供了两套绑定方案
  1. Must bind(可以简单理解为当获取参数映射时如果出现错误会panic),** MustBindWith 支持如下方式:** Bind , BindJSON , BindXML , BindQuery , BindYAML,注意点: 如果存在绑定错误,则终⽌请求,使⽤ c.AbortWithError (400) .SetType (ErrorTypeBind) 即可。将响应状态代码设置为400,Content-Type header设置为 text/plain;charset = utf - 8 。如果在此之后设置响应代码,将会受到警告: [GIN-debug[WARNING] Headers were alreadywritten. Wanted to override status code 400 with 422 将导致已经编写了警告[GIN-debug][warning]标头。如果想更好地控制⾏为,可以考虑使⽤ShouldBind等效⽅法
  2. Should bind(可以简单理解为如果出现错误,会将错误返回由开发人员自己处理),ShouldBindWith 支持如下方式: ShouldBind , ShouldBindJSON , ShouldBindXML , ShouldBindQuery , ShouldBindYAML,这些⽅法使⽤ShouldBindWith。如果存在绑定错误,则返回错误,开发⼈员有责任适当地处理请求和错误
    在这里插入图片描述

ShouldBindWith 请求数据映射示例

  1. 在使用映射时要创建对应结构体,例如:(注意点:binding:"required"表示必须的,如果不传,解析映射时会报错)
//如果调用方传递的是form表单,则表单中的key值要与当前结构体中form对应的key值一样
//同理,如果是json或xml也要与当前结构体中json,xml对应的key值一样

//添加 binding:"required" 表示该字段为必须的,如果不传在解析映射时会报错
type Login struct {
	User     string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`
	Password string `form:"password" json:"password" uri:"password"xml:"password" binding:"required"`
	//不能为空并且大于10
    Age      int       `form:"age" binding:"required,gt=10"`
    Name     string    `form:"name" binding:"required"`
    Birthday time.Time `form:"birthday" time_format:"2006-01-02" time_utc:"1"`
}
  1. 在不知道调用方传递的数据类型情况下使用ShouldBind()方法进行解析,示例
package main

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

type Login struct {
	User     string `form:"username" json:"user" uri:"user" xml:"user"binding:"required"`
	Password string `form:"password" json:"password" uri:"password"xml:"password" binding:"required"`
}

func main() {
	router := gin.Default()
	//1.binding JSON
	// Example for binding JSON ({"user": "ls", "password": "123456"})
	router.POST("/loginJSON", JsonFunc)
	router.Run(":8080")
}

func JsonFunc(c *gin.Context) {

	//1.创建接收参数对应的结构体变量
	var login Login

	//2.在不知道调用方传递的是什么数据类型时使用c.ShouldBindJSON(&login)
	//通过Context调用ShoudBind()方法将创建的对应结构体变量指针传递给该方法
	//方法内部首先在请求头中拿到请求类型,例如MIMEJSON..等等,根据该类型自动
	//选择对应的解析方法进行解析
	if err := c.ShouldBind(&login); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
}
  1. 注意点ShouldBind()查看源码,该方法只支持一下类型,根据Content-Type请求头,获取到指定类型后,按照指定格式获取参数进行绑定调用 ShouldBindWith()方法
func (c *Context) ShouldBind(obj interface{}) error {
	b := binding.Default(c.Request.Method, c.ContentType())
	return c.ShouldBindWith(obj, b)
}

func Default(method, contentType string) Binding {
	if method == http.MethodGet {
		return Form
	}

	switch contentType {
	case MIMEJSON:
		return JSON
	case MIMEXML, MIMEXML2:
		return XML
	case MIMEPROTOBUF:
		return ProtoBuf
	case MIMEMSGPACK, MIMEMSGPACK2:
		return MsgPack
	case MIMEYAML:
		return YAML
	case MIMEMultipartPOSTForm:
		return FormMultipart
	default: // case MIMEPOSTForm:
		return Form
	}
}
  1. 如果明确调用方传递的数据类型,可以直接调用ShouldBindXXX()对应该类型的指定方法进行解析,例如ShouldBindJSON()
if err := c.ShouldBindJSON(&login); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
}

//另外还有
c.ShouldBindXML(&login)
c.ShouldBindYAML(&login)
c.ShouldBindHeader(&login)
c.ShouldBindQuery(&login)
//如果前端使用url参数,例如":8080/test/123/"数据2""",可以使用 c.ShouldBindUri(&login)
c.ShouldBindUri(&login)
  1. 5.gin内部整合了validator库go validator数据校验示例使⽤绑定⽅法时,可以指定参数校验格式,例如使用 binding:“required” 修饰非空等等

ShouldBindHeader 将请求头绑定到一个结构体或接口示例

  1. 可以使用c.ShouldBindHeader方法来将请求头绑定到一个结构体或接口,并使用标签来指定绑定规则
func main() {
	r := gin.Default() // 创建一个默认的gin引擎

	// 定义一个结构体,用来接收请求头中的数据
	type Header struct {
		UserID   string `header:"User-ID"`   // 绑定User-ID字段到UserID属性
		Token    string `header:"Token"`     // 绑定Token字段到Token属性
		ClientIP string `header:"Client-IP"` // 绑定Client-IP字段到ClientIP属性
	}

	// 注册一个GET路由
	r.GET("/info", func(c *gin.Context) {
		// 创建一个Header对象
		var header Header
		// 将请求头绑定到Header对象上
		if err := c.ShouldBindHeader(&header); err != nil {
			// 绑定失败,返回400状态码和错误信息,并终止后续处理
			c.String(400, err.Error())
			c.Abort()
			return
		}

MustBindWith 方式

  1. 与前面的一样也要先创建接收数据对应的结构体变量
  2. 不同的是如果解析失败会panic
  3. 示例
func JsonFunc(c *gin.Context) {

	//1.创建接收参数对应的结构体变量
	var login Login

	//2.c.Bind() 使用的是MustBindWith解析方式,该方式如果解析失败会直接panic将一个400写入响应头中
	//Bind():在不知道调用方数据类型时使用该方法,内部会通过请求头先获取到数据类型然后进行解析
	if err := c.Bind(&login); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if login.User != "ls" || login.Password != "123456" {
		c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
}

//另外还支持
c.BindJSON(&login)
c.BindXML(&login)
c.BindYAML(&login)
......等等
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值