gin框架配合go-playground/validator完成json的验证以及json验证错误翻译成中文
安装 go-playground/validator
go get github.com/go-playground/validator/v10
代码如下
package main
import (
"fmt"
"net/http"
"reflect"
"strings"
"github.com/gin-gonic/gin"
"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"
)
type LoginForm struct {
User string `json:"user" binding:"required,min=3,max=10"`
Password string `json:"password" binding:"required"`
}
type SignupForm struct {
Age uint8 `json:"age" binding:"gte=18,lte=130"`
Name string `json:"name" binding:"required,min=3"`
Email string `json:"email" binding:"required,email"`
Password string `json:"password" binding:"required,min=6"`
RePassword string `json:"re_password" binding:"required,eqfield=Password"` // 跨字段验证
}
var trans ut.Translator
func removeTopStruct(fields map[string]string) map[string]string {
// "LoginForm.user": "user长度不能超过10个字符"
// 提取user,去掉LoginForm -- "user": "user长度不能超过10个字符"
rsp := make(map[string]string)
for field, err := range fields {
rsp[field[strings.Index(field, ".")+1:]] = err
}
return rsp
}
func InitTrans(locale string) (err error) {
// 修改gin框架中的validator引擎属性,实现定制
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
// 注册一个获取json的tag的自定义方法
// "LoginForm.User": "User长度不能超过10个字符"
// 将大写的User替换为json中定义的tag标签 -- "LoginForm.user": "user长度不能超过10个字符"
v.RegisterTagNameFunc(func(field reflect.StructField) string {
name := strings.SplitN(field.Tag.Get("json"), ",", 2)[0]
if name == "-"{
return ""
}
return name
})
zhT := zh.New() // 中文翻译器
enT := en.New() // 英文翻译器
// 第一个参数是备用的语言环境,后面的参数是应该支持的语言环境
uni := ut.New(enT, zhT, enT)
trans, ok = uni.GetTranslator(locale)
fmt.Println(ok)
if !ok {
return fmt.Errorf("uni.GetTranslator(%s)", locale)
}
switch locale {
case "en":
en_translations.RegisterDefaultTranslations(v, trans)
case "zh":
zh_translations.RegisterDefaultTranslations(v, trans)
default:
en_translations.RegisterDefaultTranslations(v, trans)
}
return
}
return
}
func main() {
if err := InitTrans("zh"); err != nil {
fmt.Println("初始化翻译器错误")
return
}
r := gin.Default()
r.POST("/login", loginView)
r.POST("/signup", signupView)
r.Run()
}
func signupView(context *gin.Context) {
var signupForm SignupForm
if err := context.ShouldBind(&signupForm); err != nil {
context.String(http.StatusBadRequest, err.Error())
return
}
context.JSON(http.StatusOK, gin.H{"message": "注册成功"})
}
func loginView(context *gin.Context) {
var loginForm LoginForm
if err := context.ShouldBind(&loginForm); err != nil {
errs, ok := err.(validator.ValidationErrors)
if !ok{
context.String(400, err.Error())
}
context.JSON(400, removeTopStruct(errs.Translate(trans)))
return
}
context.JSON(http.StatusOK, gin.H{"message": "登录成功"})
}
go-playground/validator源码
go-playground/validator官方文档
json验证错误翻译成中文参考源码
自定义验证器不翻译解决办法
- 自定义验证器代码
// 自定义验证器
func ValidateMobile(fl validator.FieldLevel) bool {
mobile := fl.Field().String()
// 使用正则表达式判断mobile是否合法
//pattern := "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\d{8}$"
pattern := `^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\d{8}$`
ok, _ := regexp.MatchString(pattern, mobile)
if !ok{
return false
}
return true
}
- 注册验证器,同时解决自定义验证器不翻译问题
// 5. 注册验证器
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
_ = v.RegisterValidation("mobile", myvalidator.ValidateMobile)
// 解决自定义验证器不翻译问题, 注意上面注册的自定义验证器mobile要和下面的保持一致
_ = 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
})
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)