当前位置:网站首页>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")
}
边栏推荐
- resize2fs: 超级块中的幻数有错(Bad magic number in super-block )
- leetcode-592:分数加减运算
- 记 - 踩坑-实时数仓开发 - doris/pg/flink
- Relative date used by filter in salesforce
- SS command details
- 模拟卷Leetcode【普通】061. 旋转链表
- win11系统错误:由于找不到 iertutil.dll,无法继续执行代码。重新安装程序可能会解决此问题
- Teacher Wu Enda machine learning course notes 01 introduction
- 基于C语言设计的学生成绩排名系统
- MVFuseNet:Improving End-to-End Object Detection and Motion Forecasting through Multi-View Fusion of
猜你喜欢

Leetcode-592: fraction addition and subtraction

LeetCode 879. 盈利计划

Is online legend software testing training really so black hearted? Are they all scams?

win11系统错误:由于找不到 iertutil.dll,无法继续执行代码。重新安装程序可能会解决此问题

Actual combat! Talk about how to solve the deep paging problem of MySQL

Thread - thread safety - thread optimization

C language memory stack and heap usage

vscode通过remotessh结合xdebug远程调试php解决方案

Decompilation of wechat applet

【flask入门系列】Flask-SQLAlchemy的安装与配置
随机推荐
没那么简单的单例模式
MVFuseNet:Improving End-to-End Object Detection and Motion Forecasting through Multi-View Fusion of
Leetcode-592: fraction addition and subtraction
Unity free element special effect recommendation
Teacher wangshuyao's notes on operations research course 08 linear programming and simplex method (simplex method)
数据库系统概述
Flink实时仓库-DWD层(下单-多张表实现join操作)模板代码
Teacher Cui Xueting's course notes on optimization theory and methods 00 are written in the front
图像加噪声与矩阵求逆
微信小程序的反编译
Summary of 2022 SQL classic interview questions (with analysis)
Actual combat! Talk about how to solve the deep paging problem of MySQL
好文佳句摘录
线程 - 线程安全 - 线程优化
Unity探索地块通路设计分析 & 流程+代码具体实现
[cf1054h] epic Revolution -- number theory, convolution, arbitrary modulus NTT
Flink实时仓库-DWD层(kafka-关联mysql的lookup join)模板代码
Connecting PHP 7.4 to Oracle configuration on Windows
MySQL: what happens in the bufferpool when you crud? Ten pictures can make it clear
模拟卷Leetcode【普通】093. 复原 IP 地址