1. 程式人生 > 其它 >gin框架中的引數驗證

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"  // 中國:東八時區
}