Gin框架的数据校验

发布时间:2024年01月08日

抛出问题:

使用默认的数据校验,校验失败时,返回的提示信息为英文,且根据提示信息没法判断校验失败的原因,体验感很差。

解决:

自定义校验,注册翻译器

涉及的包:

    en2 "github.com/go-playground/locales/en"
    zh2 "github.com/go-playground/locales/zh"
    ut "github.com/go-playground/universal-translator"
    en_translations "github.com/go-playground/validator/v10/translations/en"
    zh_translations "github.com/go-playground/validator/v10/translations/zh"

结构体在校验时不在使用binding,使用validate。

var query struct {
		Name        string `form:"name" json:"name,omitempty" validate:"omitempty,max=128"`
		Id          int    `form:"id" json:"id,omitempty" validate:"omitempty,numeric,gte=1"`
		PerShopId   string `form:"per_shop_id" json:"per_shop_id,omitempty"`
		PerCategory string `form:"per_category" json:"per_category,omitempty"`
		PerErpArea  string `form:"per_erp_area" json:"per_erp_area,omitempty"`
		Page        int    `form:"page" json:"page" validate:"required,gte=1"`
		PageSize    int    `form:"page_size" json:"page_size" validate:"required,gte=1"`
	}

构建语言转换器及注册:

  • 将Validate做成一个单例。手动定义了一个ErrorOnce(仿照标准库的sync.Once),目的在于初始化函数失败后,后续可以继续初始化该单例
  • GetValidate():通过该函数获取校验器。其中创建了validate,并为其注册了中文翻译器
  • GetErrInfo():用于获取校验结果,如果有错误,会以Map和切片的结构返回校验错误信息,根据需求确定
import (
	"fmt"
	"github.com/gin-gonic/gin"
	lzh "github.com/go-playground/locales/zh"
	ut "github.com/go-playground/universal-translator"
	"github.com/go-playground/validator/v10"
	translations "github.com/go-playground/validator/v10/translations/zh"
	"strings"
	"sync"
	"sync/atomic"
)

var (
	uni          *ut.UniversalTranslator
	validate     *validator.Validate
	validateOnce = &ErrorOnce{}
	trans        ut.Translator
)
type ErrorOnce struct {
	m    sync.Mutex
	done uint32
}

func (v *ErrorOnce) Do(f func() error) error {
	if atomic.LoadUint32(&v.done) == 1 {
		return nil
	}
	return v.doSlow(f)
}

func (v *ErrorOnce) doSlow(f func() error) error {
	v.m.Lock()
	defer v.m.Unlock()
	var err error
	if v.done == 0 {
		err = f()
		if err == nil {
			atomic.StoreUint32(&v.done, 1)
		}
	}
	return err
}

func GetValidate() *validator.Validate {
	err := validateOnce.Do(func() error {
		zh := lzh.New()
		uni = ut.New(zh)
		validate = validator.New()
		trans, _ = uni.GetTranslator("zh")
		return translations.RegisterDefaultTranslations(validate, trans)
	})
	fmt.Println("GetValidate-err->", err)
	return validate
}

func GetErrInfo(err error) (map[string]string, []string) {
	errs := err.(validator.ValidationErrors)
	sliceErrs := make([]string, len(errs))
	for i, e := range errs {
		sliceErrs[i] = e.Translate(trans)
	}
	return errs.Translate(trans), sliceErrs
}

使用:

  • 进行参数绑定
  • 获取校验器校验参数,并获取error
err := c.ShouldBindQuery(&query)
if err != nil {
    c.JSON(http.StatusBadRequest, info)
	return
}
//参数校验
if err = GetValidate().Struct(query); err != nil {
	info, _ := GetErrInfo(err)
	c.JSON(http.StatusBadRequest, info)
	return
}

文章来源:https://blog.csdn.net/q79030/article/details/135459229
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。