GIN下关于参数的多次绑定问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GIN下关于参数的多次绑定问题相关的知识,希望对你有一定的参考价值。
参考技术A 在使用Gin的关于参数帮的问题上,比如当我的某个接口必须要都支持GET和HOST的等方法的时候,目前我所直达的方式是:但是得再使用的过程中有疑惑的地方是:
参数的多次的绑定的解析的情况,比如,我再自定义的中间件里面也需要获取相关的参数进行参数解析和绑定,在路由API的内部也需要提取参数进行绑定解析到结构体上的时候,就会出现多次绑定的失效的问题。
中间件内需要绑定的结构体:
如:
POST的情况:
使用application/json进行提交参数内容
ShouldBindJSON--中间件绑定解析后,在下一步的API内在使用ShouldBindJSON的时候就错误了。
需使用:ShouldBindBodyWith 的情况,则两个都可以正常的解析且绑定。
GET的情况下和POST的(application/form-data):
多次绑定的解析则直接的使用:
所以再兼容多种请求的方式下目前只能做类型判断处理
调用的地方:
Gin JSON数据绑定和参数验证以及自定义验证的错误信息
原创不易,未经允许,请勿转载。
一、JSON数据绑定
首先定义一个接受数据用的DTO
结构体,叫做LoginDTO
type LoginDto struct
Username string `json:"username" binding:"required" msg:"用户名不能为空"`
Password string `json:"password" binding:"min=3,max=6" msg:"密码长度不能小于3大于6"`
Email string `json:"email" binding:"email" msg:"邮箱地址格式不正确"`
几个tag
的作用分别是:
json
:用于绑定json数据,对应json上面的键值binding
:字段的验证规则,使用的是https://github.com/go-playground/validatormsg
:验证错误的提示信息
注册路由,获取从请求体中获取获取参数
package main
import "github.com/gin-gonic/gin"
type LoginDto struct
Username string `json:"username" binding:"required" msg:"用户名不能为空"`
Password string `json:"password" binding:"min=3,max=6" msg:"密码长度不能小于3大于6"`
Email string `json:"email" binding:"email" msg:"邮箱地址格式不正确"`
func main()
r := gin.Default()
r.POST("/login", func(c *gin.Context)
userDto := &LoginDto // 要指针类型
if err := c.ShouldBindJSON(userDto); err != nil
c.JSON(200, gin.H"message": err.Error())
else
c.JSON(200, gin.H
"message": userDto,
)
)
r.Run(":8080")
运行一下上面的代码,用postman传入下列参数测试一下
"username":"1",
"password":"jiang",
"email":"test@qq.com"
返回的结果如果是下面这样,则代码没什么问题。
"message":
"username": "1",
"password": "jiang",
"email": "test@qq.com"
二、参数验证
一些接口的参数需要满足特定的要求,例如username
这个字段不能为空,也不能超过一定长度。如果要我们接受好参数再手动判断就太麻烦了,gin框架可以帮助我们在绑定参数的时候顺带的去验证参数是否符合我们的要求。
添加验证的方法也很简单。只要在tag
中添加binding:"..."
验证规则即可
type LoginDto struct
Username string `json:"username" binding:"required"` // 表示该字段是必须的,不能为空
Password string `json:"password" binding:"min=3,max=6"` // 如果该字段是字符串的话,长度不能小于3,不能大于6
Email string `json:"email" binding:"email"` // 该字段要符合邮箱地址
更多验证规则可以看这个文档 https://github.com/go-playground/validator,因为gin
内部的验证也是引用的这个库。
三、自定义验证的错误信息
当验证不通过时,会给出错误的信息,但是原始的错误信息不太友好,不利于用户查看
Key: 'LoginDto.Username' Error:Field validation for 'Username' failed on the 'required' tag
所以当出现错误时,我们希望可以返回我们自定义的错误信息,这样方便调用方差错。
在结构体的字段中,添加一个msg
的tag,表示提示信息,当该字段验证不通过时,就返回msg
的提示
type LoginDto struct
Username string `json:"username" binding:"required" msg:"用户名不能为空"`
Password string `json:"password" binding:"min=3,max=6" msg:"密码长度不能小于3大于6"`
Email string `json:"email" binding:"email" msg:"邮箱地址格式不正确"`
当出现错误时,就可以来获取出错字段上的msg。
err
:这个参数为ShouldBindJSON
返回的错误信息obj
:这个参数为绑定的结构体- 还有一点要注意的是,validator这个包要引用v10这个版本的,否则会出错
func GetValidMsg(err error, obj interface) string
getObj := reflect.TypeOf(obj)
if errs, ok := err.(validator.ValidationErrors); ok
for _, e := range errs
if f, exist := getObj.Elem().FieldByName(e.Field()); exist
return f.Tag.Get("msg") //错误信息不需要全部返回,当找到第一个错误的信息时,就可以结束
return err.Error()
完整的代码如下
package main
import (
"fmt"
"reflect"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
)
type LoginDto struct
Username string `json:"username" binding:"required" msg:"用户名不能为空"`
Password string `json:"password" binding:"min=3,max=6" msg:"密码长度不能小于3大于6"`
Email string `json:"email" binding:"email" msg:"邮箱地址格式不正确"`
func GetValidMsg(err error, obj interface) string
fmt.Println("sherlock")
getObj := reflect.TypeOf(obj)
if errs, ok := err.(validator.ValidationErrors); ok
for _, e := range errs
if f, exist := getObj.Elem().FieldByName(e.Field()); exist
return f.Tag.Get("msg")
return err.Error()
func main()
r := gin.Default()
r.POST("/login", func(c *gin.Context)
userDto := &LoginDto
if err := c.ShouldBindJSON(userDto); err != nil
c.JSON(200, gin.H
"status": "err",
"message": GetValidMsg(err, userDto),
)
else
c.JSON(200, gin.H
"status": "change",
"message": userDto,
)
)
r.Run(":8080")
用postman传入下列参数测试一下
"username":"",
"password":"jiang",
"email":"test@qq.com"
会返回下列错误提示
"message": "用户名不能为空",
"status": "err"
拒绝白嫖从一键三连开始!
原创不易,未经允许,请勿转载。
以上是关于GIN下关于参数的多次绑定问题的主要内容,如果未能解决你的问题,请参考以下文章