gin框架中的参数验证

结构体验证

用gin框架的数据验证,可以不用解析数据,减少if else,会简洁许多。

  1. 处理请求方法
func structValidator(context *gin.Context) {
	var person Person
	if err := context.ShouldBind(&person); err != nil {
		fmt.Println(err)
		context.String(http.StatusBadRequest, "failed")
		return
	}
	context.JSON(http.StatusOK, &person)
}
  1. 验证结构体
type Person struct {
	// 不能为空并且大于10
	Age int `json:"age" form:"age" binding:"required,gt=10"`
	Name string `json:"name" form:"name" binding:"required"`
	Birthday time.Time `json:"birthday" form:"birthday" time_format:"2006-01-02 15:04:05" time_utc:"0"`
}

自定义验证 V10版本

依赖:github.com/go-playground/validator/v10

type Person struct {
	// 不能为空并且大于10
	Age int `json:"age" form:"age" binding:"required,gt=10"`
	// 2、在参数 binding 上使用自定义的校验方法函数注册时候的名称
	Name     string    `json:"name" form:"name" binding:"NotNullAndAdmin"`
	Birthday time.Time `json:"birthday" form:"birthday" time_format:"2006-01-02"`
}

func NotNullAndAdmin(fl validator.FieldLevel) bool {
	if value, ok := fl.Field().Interface().(string); ok {
		// 字段不能为空,并且不等于  admin
		return value != "" && !("admin" == value)
	}
	return false
}

func RegisterValidator() {
	// 将我们自定义的校验方法注册到validator中
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		// 这里的 key 和 fn 可以不一样最终在 struct 使用的是 key
		v.RegisterValidation("NotNullAndAdmin", NotNullAndAdmin)
	}

}

func main() {
	// 注册验证器
	blog.RegisterValidator()
}

自定义验证器 V8版本

点击查看代码
package main
 
import (
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"gopkg.in/go-playground/validator.v8"
	"net/http"
	"reflect"
	"time"
)
 
//binding 绑定一些验证请求参数,自定义标签bookabledate表示可预约的时期
type Booking struct {
	CheckIn  time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"`
	CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckOut,bookabledate" time_format:"2006-01-02"`
}
 
 
//定义bookabledate标签对应的验证方法
func bookableDate(
	v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,
	field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,
) bool {
	if date, ok := field.Interface().(time.Time); ok {
		today := time.Now()
 
		if  date.Unix() > today.Unix() {
			return true
		}
	}
	return false
}
 
 
func main() {
	route := gin.Default()
 
        //将验证方法注册到验证器中
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		v.RegisterValidation("bookabledate", bookableDate)
	}
 
	route.GET("/bookable", getBookable)
	route.Run(":8080")
}
 
func getBookable(c *gin.Context) {
	var b Booking
	if err := c.ShouldBindWith(&b, binding.Query); err == nil {
		c.JSON(http.StatusOK, gin.H{"message": "Booking dates are valid!"})
	} else {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
	}
}

V10 版本示例2

func RegisterValidator() {
	// 将我们自定义的校验方法注册到validator中
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		// 这里的 key 和 fn 可以不一样最终在 struct 使用的是 key
		v.RegisterValidation("NotNullAndAdmin", NotNullAndAdmin)

		v.RegisterValidation("bookableDate", bookableDate)
	}
}

type Booking struct {
	// 定义一个预约的时间大于今天的时间
	CheckIn time.Time `json:"check_in" binding:"required,bookableDate" time_format:"2006-01-02"`
	// gtfield=CheckIn退出的时间大于预约的时间
	CheckOut time.Time `json:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02"`
}

func bookableDate(fl validator.FieldLevel) bool {
	if v, ok := fl.Field().Interface().(time.Time); ok {
		currentTime := time.Now().Unix()
		if currentTime > v.Unix() {
			return false
		}
	}
	return true
}

请求参数:

{
    "check_in": "2021-12-13T8:16:25Z",  // UTC时区
    "check_out": "2021-12-13T16:16:26+08:00"  // 中国:东八时区
}
posted @ 2021-12-13 16:45  专职  阅读(1142)  评论(0编辑  收藏  举报