gin表单验证

简介

Gin使用go-playground/validator验证参数;
官方文档

表单验证

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

type SignUpForm struct {
	// 参数age必填;大于等于1小于等于100
	Age uint8 `json:"age" binding:"required,gte=1,lte=100"`
	// 参数name必填;最小长度3最大长度15
	Name string `json:"name" binding:"required,min=3,max=15"`
	// 参数email必填;必须符合email规范
	Email string `json:"email" binding:"required,email"'`
	// 参数password必填
	Password string `json:"password" binding:"required"`
	// 参数re_password必填;内容必须与password相同
	RePassword string `json:"re_password" binding:"required,eqfield=Password"`
}

func main() {
	r := gin.Default()
	r.POST("/signup", func(context *gin.Context) {
		var signUpFrom SignUpForm
		if err := context.ShouldBind(&signUpFrom); err != nil {
			// 参数不符合规则返回400
			context.JSON(http.StatusBadRequest, gin.H{
				"error": err.Error(),
			})
			return
		}
		context.JSON(http.StatusOK, gin.H{
			"mag": "注册成功",
		})
	})
	r.Run(":8081")
}

gin表单验证_第1张图片
gin表单验证_第2张图片

将错误翻译成中文

package main

import (
	"fmt"
	"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"
	en1 "github.com/go-playground/validator/v10/translations/en"
	zh1 "github.com/go-playground/validator/v10/translations/zh"
	"log"
	"net/http"
)

var trans ut.Translator

type SignUpForm struct {
	// 参数age必填;大于等于1小于等于100
	Age uint8 `json:"age" binding:"required,gte=1,lte=100"`
	// 参数name必填;最小长度3最大长度15
	Name string `json:"name" binding:"required,min=3,max=15"`
	// 参数email必填;必须符合email规范
	Email string `json:"email" binding:"required,email"'`
	// 参数password必填
	Password string `json:"password" binding:"required"`
	// 参数re_password必填;内容必须与password相同
	RePassword string `json:"re_password" binding:"required,eqfield=Password"`
}

func InitTrans(locale string) error {
	// 修改gin框架中的validator引擎属性,实现定制
	validate := binding.Validator.Engine().(*validator.Validate)
	zhT := zh.New() // 中文翻译器
	enT := en.New() // 英文翻译器
	// 第一个参数是备用的语言环境;后面的参数是应该支持的语言环境
	uni := ut.New(zhT, zhT, enT)
	var ok bool
	trans, ok = uni.GetTranslator(locale)
	if !ok {
		return fmt.Errorf("uni.GetTranslator(%s)", locale)
	}
	if locale == "en" {
		// 英文
		en1.RegisterDefaultTranslations(validate, trans)
	} else {
		// 非英文的统一使用中文
		zh1.RegisterDefaultTranslations(validate, trans)
	}
	return nil
}

func main() {
	// 初始化翻译器
	if err := InitTrans("zh"); err != nil {
		log.Println("初始化翻译器错误")
		return
	}
	r := gin.Default()
	r.POST("/signup", func(context *gin.Context) {
		var signUpFrom SignUpForm
		if err := context.ShouldBind(&signUpFrom); err != nil {
			errors, ok := err.(validator.ValidationErrors)
			if !ok {
				// 不属于类型校验错误时就直接原样返回
				context.JSON(http.StatusBadRequest, gin.H{
					"msg": err.Error(),
				})
				return
			}
			// 参数不符合规则返回400
			context.JSON(http.StatusBadRequest, gin.H{
				"error": errors.Translate(trans),
			})
			return
		}
		context.JSON(http.StatusOK, gin.H{
			"mag": "注册成功",
		})
	})
	r.Run(":8081")
}

gin表单验证_第3张图片
gin表单验证_第4张图片

返回细节处理

再发生错误时,返回值细节上还有一些问题

{
    "error": {
        "SignUpForm.Age": "Age为必填字段",
        "SignUpForm.Email": "Email为必填字段",
        "SignUpForm.Name": "Name为必填字段",
        "SignUpForm.Password": "Password为必填字段",
        "SignUpForm.RePassword": "RePassword为必填字段"
    }
}
  • 提示语里面的属性名全部都是go语言中的属性名
  • 还携带了go语言中的struct名
package main

import (
	"fmt"
	"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"
	en1 "github.com/go-playground/validator/v10/translations/en"
	zh1 "github.com/go-playground/validator/v10/translations/zh"
	"log"
	"net/http"
	"reflect"
	"strings"
)

var trans ut.Translator

type SignUpForm struct {
	// 参数age必填;大于等于1小于等于100
	Age uint8 `json:"age" binding:"required,gte=1,lte=100"`
	// 参数name必填;最小长度3最大长度15
	Name string `json:"name" binding:"required,min=3,max=15"`
	// 参数email必填;必须符合email规范
	Email string `json:"email" binding:"required,email"'`
	// 参数password必填
	Password string `json:"password" binding:"required"`
	// 参数re_password必填;内容必须与password相同
	RePassword string `json:"re_password" binding:"required,eqfield=Password"`
}

func InitTrans(locale string) error {
	// 修改gin框架中的validator引擎属性,实现定制
	if validate, ok := binding.Validator.Engine().(*validator.Validate); ok {
		// 注册一个获取json的tag的自定义方法
		validate.RegisterTagNameFunc(func(field reflect.StructField) string {
			name := strings.SplitN(field.Tag.Get("json"), ",", 2)[0]
			if name == "-" {
				// json的tag标签没有填默认"-"
				return ""
			}
			return name
		})
		zhT := zh.New() // 中文翻译器
		enT := en.New() // 英文翻译器
		// 第一个参数是备用的语言环境;后面的参数是应该支持的语言环境
		uni := ut.New(zhT, zhT, enT)
		var ok bool
		trans, ok = uni.GetTranslator(locale)
		if !ok {
			return fmt.Errorf("uni.GetTranslator(%s)", locale)
		}
		if locale == "en" {
			// 英文
			en1.RegisterDefaultTranslations(validate, trans)
		} else {
			// 非英文的统一使用中文
			zh1.RegisterDefaultTranslations(validate, trans)
		}
	}
	return nil
}

// 去除error信息中的go语言的struct名
func removeTopStruct(fileds map[string]string) map[string]string {
	res := map[string]string{}
	for k, v := range fileds {
		res[k[strings.Index(k, ".")+1:]] = v
	}
	return res
}

func main() {
	// 初始化翻译器
	if err := InitTrans("zh"); err != nil {
		log.Println("初始化翻译器错误")
		return
	}
	r := gin.Default()
	r.POST("/signup", func(context *gin.Context) {
		var signUpFrom SignUpForm
		if err := context.ShouldBind(&signUpFrom); err != nil {
			errors, ok := err.(validator.ValidationErrors)
			if !ok {
				// 不属于类型校验错误时就直接原样返回
				context.JSON(http.StatusBadRequest, gin.H{
					"msg": err.Error(),
				})
				return
			}
			// 参数不符合规则返回400
			context.JSON(http.StatusBadRequest, gin.H{
				"error": removeTopStruct(errors.Translate(trans)),
			})
			return
		}
		context.JSON(http.StatusOK, gin.H{
			"mag": "注册成功",
		})
	})
	r.Run(":8081")
}

gin表单验证_第5张图片
gin表单验证_第6张图片

你可能感兴趣的:(Gin学习,golang,github,开发语言,gin)