当前位置:网站首页>gin 参数验证
gin 参数验证
2022-07-29 06:20:00 【Mar丶流年】
前言
gin的参数验证是集成了 https://github.com/go-playground
参数验证
使用 gin.Context中ShouldBind(obj)方法
obj 通过tag设置验证规则
接收参数字段设置
//json:“json_name” 代表json格式收取json_name参数值到Name
//form:"form_name" 代表表单格式收取form_name参数值到Name
//xml:"xml_name" 代表xml格式收取xml_name参数到Name
type Register struct {
Name string `json:"json_name" form:"form_name" xml:"xml_name"`
}
参数条件限制
更多tag 请查看官方文档(https://pkg.go.dev/github.com/go-playground/validator/v10#hdr-Using_Validator_Tags)
//binding:后为条件限制
//required:必填
//min:最小长度
//max:最大长度
type Register struct {
Name string `json:"json_name" form:"form_name" xml:"xml_name" binding:"required,min=3,max=10"`
}
输出错误信息
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
type Register struct {
Name string `json:"json_name" form:"form_name" xml:"xml_name" binding:"required,min=3,max=10"`
}
func main() {
r := gin.Default()
r.POST("/register", func(c *gin.Context) {
r := &Register{
}
err := c.ShouldBind(r)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "ok",
})
})
r.Run(":8080")
}
验证信息中文处理
未进行中文处理的验证错误信息是这个样子的:Key: ‘Register.Name’ Error:Field validation for ‘Name’ failed on the ‘required’ tag
首先先注册翻译器,然后创建通用翻译器,从通用翻译器中获取指定的翻译器(封装过的),然后将其绑定到gin的验证器上。
验证器返回的错误转换成 go-playground 的 ValidationErrors类型,调用Translate 指定翻译器进行翻译
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"
en_translation "github.com/go-playground/validator/v10/translations/en"
zh_translation "github.com/go-playground/validator/v10/translations/zh"
"net/http"
)
type Register struct {
Name string `json:"json_name" form:"form_name" xml:"xml_name" binding:"required,min=3,max=10"`
}
var trans ut.Translator
func initTranslator(language string) error {
//转换成go-playground的validator
validate, ok := binding.Validator.Engine().(*validator.Validate)
if ok {
//创建翻译器
zhT := zh.New()
enT := en.New()
//创建通用翻译器
//第一个参数是备用语言,后面的是应当支持的语言
uni := ut.New(enT, enT, zhT)
//从通过中获取指定语言翻译器
trans, ok = uni.GetTranslator(language)
if !ok {
return fmt.Errorf("not found translator %s", language)
}
//绑定到gin的验证器上,对binding的tag进行翻译
switch language {
case "zh":
err := zh_translation.RegisterDefaultTranslations(validate, trans)
if err != nil {
return err
}
default:
err := en_translation.RegisterDefaultTranslations(validate, trans)
if err != nil {
return err
}
}
}
return nil
}
func main() {
err := initTranslator("zh")
if err != nil {
panic(err)
}
r := gin.Default()
r.POST("/register", func(c *gin.Context) {
r := &Register{
}
err := c.ShouldBind(r)
if err != nil {
if errors, ok := err.(validator.ValidationErrors); ok {
//调用指定翻译器进行翻译
c.JSON(http.StatusBadRequest, gin.H{
"error": errors.Translate(trans),
})
} else {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
}
return
}
c.JSON(http.StatusOK, gin.H{
"message": "ok",
})
})
r.Run(":8080")
}
返回的错误格式处理
上面返回的错误格式是这个样子的
{
"error": {
"Register.Name": "Name为必填字段"
}
}
首先我通过JSON格式请求的,error中的key应该是json_name,value
应该是json_name为必填字段
理想型数据结构
{
"error": {
"json_name": "json_name为必填字段"
}
}
json_name 可以通过 RegisterTagNameFunc 设置返回字段json_name,但是就算设置json_name,但是key还是 Register.json_name。
解决方案:对错误结果进行处理,剔除 Register 部分
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"
en_translation "github.com/go-playground/validator/v10/translations/en"
zh_translation "github.com/go-playground/validator/v10/translations/zh"
"net/http"
"reflect"
"strings"
)
type Register struct {
Name string `json:"json_name" form:"form_name" xml:"xml_name" binding:"required,min=3,max=10"`
}
var trans ut.Translator
func initTranslator(language string) error {
//转换成go-playground的validator
validate, ok := binding.Validator.Engine().(*validator.Validate)
validate.RegisterTagNameFunc(func(field reflect.StructField) string {
// json:"json_name" form:"form_name" xml:"xml_name" binding:"required,min=3,max=10"
// 设置返回 json tag 中的内容 如:json_names
return field.Tag.Get("json")
})
if ok {
//创建翻译器
zhT := zh.New()
enT := en.New()
//创建通用翻译器
//第一个参数是备用语言,后面的是应当支持的语言
uni := ut.New(enT, enT, zhT)
//从通过中获取指定语言翻译器
trans, ok = uni.GetTranslator(language)
if !ok {
return fmt.Errorf("not found translator %s", language)
}
//对binding的tag进行翻译
switch language {
case "zh":
err := zh_translation.RegisterDefaultTranslations(validate, trans)
if err != nil {
return err
}
default:
err := en_translation.RegisterDefaultTranslations(validate, trans)
if err != nil {
return err
}
}
}
return nil
}
func remove(errors map[string]string) map[string]string {
result := map[string]string{
}
for key, value := range errors {
result[key[strings.Index(key, ".")+1:]] = value
}
return result
}
func main() {
err := initTranslator("zh")
if err != nil {
panic(err)
}
r := gin.Default()
r.POST("/register", func(c *gin.Context) {
r := &Register{
}
err := c.ShouldBind(r)
if err != nil {
if errors, ok := err.(validator.ValidationErrors); ok {
//调用指定翻译器进行翻译
c.JSON(http.StatusBadRequest, gin.H{
//调用自定义函数去除Register部分
"error": remove(errors.Translate(trans)),
})
} else {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
}
return
}
c.JSON(http.StatusOK, gin.H{
"message": "ok",
})
})
r.Run(":8080")
}
边栏推荐
- 二次元卡通渲染——进阶技巧
- IDEA找不到Database解决方法
- 猜数字//第一次使用生成随机数
- 线程 - 线程安全 - 线程优化
- Summary of 2022 SQL classic interview questions (with analysis)
- pytest合集(7)— 参数化
- MySQL: what happens in the bufferpool when you crud? Ten pictures can make it clear
- 谷歌零碎笔记之JWT(草稿)
- 上采样之反卷积操作
- Student status management system based on C language design
猜你喜欢

Basic knowledge of MySQL (high frequency interview questions)

记 - 踩坑-实时数仓开发 - doris/pg/flink

CVPR2022Oral专题系列(一):低光增强

Thread synchronization - producers and consumers, tortoise and rabbit race, dual thread printing

10 frequently asked JVM questions in interviews

Unity free element special effect recommendation

spark学习笔记(七)——sparkcore核心编程-RDD序列化/依赖关系/持久化/分区器/累加器/广播变量

Revolution of game assets

Flink实时仓库-DWD层(流量域)模板代码

解决CSDN因版权不明而无法发布博客的问题
随机推荐
Leetcode-1331: array ordinal conversion
leetcode-592:分数加减运算
城市花样精~侬好!DESIGN#可视化电台即将开播
模拟卷Leetcode【普通】093. 复原 IP 地址
Flink real-time warehouse DWD layer (transaction domain - additional purchase dimension degradation processing) template code
MySQL: what happens in the bufferpool when you crud? Ten pictures can make it clear
Teacher Wu Enda's machine learning course notes 03 review of linear algebra
Student status management system based on C language design
Teacher wangshuyao's notes on operations research 02 fundamentals of advanced mathematics
Simulation volume leetcode [normal] 222. number of nodes of complete binary tree
实战!聊聊如何解决MySQL深分页问题
Thread - thread safety - thread optimization
Ali gave several SQL messages and asked how many tree search operations need to be performed?
1172. 餐盘栈 有序列表+栈
Overview of database system
Teacher wangshuyao's notes on operations research 04 fundamentals of linear algebra
Teacher wangshuyao's notes on operations research 05 linear programming and simplex method (concept, modeling, standard type)
Invalid access control
DM数据守护集群搭建
Flink real-time warehouse DWD layer (order placing multiple tables to realize join operation) template code