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数据绑定和参数验证以及自定义验证的错误信息

原创不易,未经允许,请勿转载。

博客主页:https://xiaojujiang.blog.csdn.net/

一、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的作用分别是:

注册路由,获取从请求体中获取获取参数

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"





拒绝白嫖从一键三连开始!

原创不易,未经允许,请勿转载。

博客主页:https://xiaojujiang.blog.csdn.net/

以上是关于GIN下关于参数的多次绑定问题的主要内容,如果未能解决你的问题,请参考以下文章

Gin-API系列请求和响应参数的检查绑定

只绑定Get参数

Gin JSON数据绑定和参数验证以及自定义验证的错误信息

Gin JSON数据绑定和参数验证以及自定义验证的错误信息

Gin JSON数据绑定和参数验证以及自定义验证的错误信息

菜鸟问下关于TextArea和Label方面的简单问题