请求体绑定: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 章再深入校验细节。