Gin 模型绑定和验证
Gin 模型绑定和验证
定义绑定的结构体:
type PhoneExistRequest struct {
Phone string `json:"phone" binding:"required,len=11" label:"手机号"`
SmsCode string `json:"sms_code" binding:"required" label:验证码`
}
错误信息翻译及绑定验证:
package requests
import (
"net/http"
"reflect"
"strings"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/locales/zh"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
zh_translations "github.com/go-playground/validator/v10/translations/zh"
)
var (
uni *ut.UniversalTranslator
validate *validator.Validate
trans ut.Translator
)
func init() {
// 注册翻译器
zh := zh.New()
uni = ut.New(zh, zh)
trans, _ = uni.GetTranslator("zh")
// 获取 gin 的校验器
validate := binding.Validator.Engine().(*validator.Validate)
// 字段的替换名称,默认是属性名称,这里改为结构体中的 json 值
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0]
if name == "-" {
return "j"
}
return name
})
// 注册翻译器
zh_translations.RegisterDefaultTranslations(validate, trans)
}
// 翻译错误信息
func Translate(err error) map[string][]string {
var result = make(map[string][]string)
errors := err.(validator.ValidationErrors)
for _, err := range errors {
result[err.Field()] = append(result[err.Field()], err.Translate(trans))
}
return result
}
// 绑定验证
func Validate(ctx *gin.Context, request interface{}) bool {
if err := ctx.ShouldBindJSON(request); err != nil {
var errors interface{}
if err.Error() == "EOF" {
errors = "没有提交参数" // 调用接口没有传入任何参数,这里会返回 EOF
} else {
errors = Translate(err)
}
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"message": "请求验证未通过",
"errors": errors,
})
return false
}
return true
}
controller 中调用:
func IsPhoneExist(ctx *gin.Context) {
request := requests.PhoneExistRequest{}
if ok := requests.Validate(ctx, &request); !ok {
return
}
// todo::验证逻辑
ctx.JSON(http.StatusOK, gin.H{
"message": "OK",
})
}
请求接口:
E:\zhpj\Desktop>curl -H "Content-Type: application/json" -X POST http://localhost:8080/login/by/phone
{
"errors":"没有提交参数",
"message":"请求验证未通过"
}
E:\zhpj\Desktop>
E:\zhpj\Desktop>curl -H "Content-Type: application/json" -X POST -d "{\"tel\":\"1234567890\"}" http://localhost:8080/login/by/phone
{
"errors":{
"phone":[
"phone为必填字段"
],
"sms_code":[
"sms_code为必填字段"
]
},
"message":"请求验证未通过"
}
E:\zhpj\Desktop>
E:\zhpj\Desktop>curl -H "Content-Type: application/json" -X POST -d "{\"phone\":\"1234567890\"}" http://localhost:8080/login/by/phone
{
"errors":{
"phone":[
"phone长度必须是11个字符"
],
"sms_code":[
"sms_code为必填字段"
]
},
"message":"请求验证未通过"
}
E:\zhpj\Desktop>
调整错误信息的结构:
func Translate(err error) []string {
errors := err.(validator.ValidationErrors)
var result = make([]string, len(errors))
for idx, err := range errors {
result[idx] = err.Translate(trans)
}
return result
}
请求接口:
E:\zhpj\Desktop>curl -H "Content-Type: application/json" -X POST -d "{\"tel\":\"1234567890\"}" http://localhost:8080/login/by/phone
{
"errors":[
"phone为必填字段",
"sms_code为必填字段"
],
"message":"请求验证未通过"
}
E:\zhpj\Desktop>

浙公网安备 33010602011771号