请求体绑定:ShouldBindJSON 与 binding tag 基础

本章解决什么问题:手动 c.PostForm/strconv 逐字段解析既啰嗦又容易漏。Gin 支持把请求数据按 tag 映射到结构体,自动完成类型转换与基础校验。本章讲 ShouldBindJSON 与 ShouldBind,并给出 binding tag 的第一印象。

结构体定义

先定义结构体:json tag 决定 JSON 字段名,binding tag 写校验规则:

type LoginForm struct {
	User     string `json:"user" binding:"required"`
	Password string `json:"password" binding:"required"`
}

JSON 请求体

客户端以 application/json 提交时,用 ShouldBindJSON:

r.POST("/login", func(c *gin.Context) {
	var f LoginForm
	if err := c.ShouldBindJSON(&f); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}
	c.JSON(200, gin.H{"user": f.User})
})

绑定失败(缺字段、类型不对、规则不过)时 ShouldBindJSON 返回 error,由 handler 决定如何响应。这正是 Should 系命名的由来:出错不自动终止,控制权交还给你。

按内容类型自动选择:ShouldBind

同一个结构体既想接 JSON、又想接表单或查询串时,给字段同时打 json 与 form 两个 tag,再用 c.ShouldBind(&f)。Gin 依据请求的 Content-Type 自动选择解码器(JSON、XML、表单、查询串等在支持列表内,完整列表以官方文档 gin-gonic.com 为准):

type CreateUser struct {
	Name  string `json:"name" form:"name" binding:"required"`
	Email string `json:"email" form:"email" binding:"required,email"`
}

r.POST("/users", func(c *gin.Context) {
	var u CreateUser
	if err := c.ShouldBind(&u); err != nil {
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}
	c.JSON(200, gin.H{"id": 1, "name": u.Name})
})

除 ShouldBind 外还有限定通道的变体:ShouldBindQuery 绑查询串、ShouldBindUri 绑路径参数、ShouldBindJSON 绑 JSON 体。

必须理解的两点

  • binding:"required" 的语义是“值非零”:空字符串、数字 0、false 都会被判为缺失(这是底层 go-playground/validator v10 的规则);
  • 默认错误信息是英文机读文本,不太适合直接回给用户,第 16 章讲翻译与自定义。

关键点

  • 绑定分“Should 系”(返回 error,自行处理)与“Must 系”(出错自动以 400 中止),教程建议用 Should 系拿到错误统一处理。
  • json/form 双 tag 让同一结构体同时服务 JSON 与表单客户端。
  • 底层校验器是 go-playground/validator v10,binding tag 的写法与 validator tag 一致,可叠加多条规则。

小结

结构体绑定把“取数 + 类型转换 + 校验”三步收成一次 c.ShouldBind* 调用。本章先建立印象:第 8 章看响应如何输出,第 15、16 章再深入校验细节。

笔记加载中…