validator和translate的简介
- validator简介:验证器是一个可以对请求数据进行验证的工具,如果不符合我们验证器定义的验证规则就返回一定的信息。
- translator简介:翻译器是和验证器配合使用的,当我们验证不通过时,我们不能直接把后端的错误直接返回给前端页面,我们需要对错误信息进行一下翻译,让前端明白验证不通过的原因是什么,而不是直接抛出错误。
实现一个全局的validator和translator
- 第一步我们需要一个表单数据来让我们验证,这就是我们用来绑定接收请求数据的结构体类型
type PassWordLoginForm struct {
Mobile string `form:"mobile" json:"mobile" binding:"required"`
PassWord string `form:"password" json:"password" binding:"required,min=3,max=20"`
}
- 第二步我们通过valiator的engine()函数来实现配置我们的全局验证器和翻译器(这里其实gin的官方给了几个很好的例子,使用默认验证器)
import (
"fmt"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/locales/en"
"github.com/go-playground/locales/zh"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
en_translations "github.com/go-playground/validator/v10/translations/en"
zh_translations "github.com/go-playground/validator/v10/translations/zh"
"reflect"
"strings"
)
func InitTrans(locale string) (err error) {
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" {
return ""
}
return name
})
zhT := zh.New()
enT := en.New()
uni := ut.New(enT, zhT, enT)
global.Trans, ok = uni.GetTranslator(locale)
if !ok {
return fmt.Errorf("uni.GetTranslator(%s)", locale)
}
switch locale {
case "en":
en_translations.RegisterDefaultTranslations(v, global.Trans)
case "zh":
zh_translations.RegisterDefaultTranslations(v, global.Trans)
default:
en_translations.RegisterDefaultTranslations(v, global.Trans)
}
return
}
return
}
- 使用:就是把初始化放在我们gin服务启动之前就可以了,调用和官方使用默认验证器是一样的使用方式,我们只是对默认的验证器进行了一些自己的配置。
func PassWordLogin(c *gin.Context) {
passwordLoginForm := forms.PassWordLoginForm{}
if err := c.ShouldBind(&passwordLoginForm); err != nil {
errs, ok := err.(validator.ValidationErrors)
if !ok {
c.JSON(http.StatusOK, gin.H{
"msg": err.Error(),
})
}
c.JSON(http.StatusBadRequest, gin.H{
"error": errs.Translate(global.Trans),
})
return
}
}
自定义验证器和翻译器
- 当我们需要对某一个数据进行单独特殊的验证规则的时候,我们就需要为他绑定一个单独的验证器(同样配套一个翻译器。。。。)。
- 第一步:同样是我们需要一个表单数据来让我们验证,这就是我们用来绑定接收请求数据的结构体类型,现在我们需要对手机号的格式进行特殊验证,如果不同过就返回失败信息。
type PassWordLoginForm struct {
Mobile string `form:"mobile" json:"mobile" binding:"required,mobile"`
PassWord string `form:"password" json:"password" binding:"required,min=3,max=20"`
}
- 第二步:定义我们的验证规则,官方文档中给出了格式,我就不再过多解释,详情请看gin中对于自定义验证器的文档。
func ValidateMobile(fl validator.FieldLevel) bool {
mobile := fl.Field().String()
ok, _ := regexp.MatchString(`^1([38][0-9]|14[579]|5[^4]|16[6]|7[1-35-8]|9[189])\d{8}$`, mobile)
if !ok {
return false
}
return true
}
- 第三步:创建我们自定义的验证器并且绑定到我们对应数据的tag(本文中的tag是mobile),自定义验证器的方式再gin官方文档的custom validator部分中有例子介绍,我就不再详细解释,同一样自定义验证器在validator的官方文档中有介绍,我们只需要使用他的translateOverride(trans ut.Translator)这个方法自定义翻译器即可。(如果你想看没有自定义翻译器的错误提示的话,可以删除掉自定义translate的部分,那个失败信息应该看的人头疼。。。。。)
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
err := v.RegisterValidation("mobile", myvalidator.ValidateMobile)
if err != nil {
zap.S().Fatalf("注册自定义validator失败:%s", err.Error())
return
}
v.RegisterTranslation("mobile", global.Trans, func(ut ut.Translator) error {
return ut.Add("mobile", "{0} 手机号格式错误!", true)
}, func(ut ut.Translator, fe validator.FieldError) string {
t, _ := ut.T("mobile", fe.Field())
return t
})
}
到这自定义验证器和翻译器也就能都基本使用了