gin框架实战(一)- HTTP请求参数校验之神器validator

发布时间:2024年01月04日

1?快速安装

使用之前,首先要获取validator这个库:

$ go get github.com/go-playground/validator/v10

2 功能

golang http 请求参数校验工具,具备复杂参数校验规则。

3 操作符

标记

标记说明

,

多操作符分割

|

或操作

-

跳过字段验证

4 常用标记说明?

标记

标记说明

required

必填

Field或Struct?validate:"required"

omitempty

空时忽略

Field或Struct?validate:"omitempty"

len

长度

Field?validate:"len=0"

eq

等于

Field?validate:"eq=0"

gt

大于

Field?validate:"gt=0"

gte

大于等于

Field?validate:"gte=0"

lt

小于

Field?validate:"lt=0"

lte

小于等于

Field?validate:"lte=0"

eqfield

同一结构体字段相等

Field?validate:"eqfield=Field2"

nefield

同一结构体字段不相等

Field?validate:"nefield=Field2"

gtfield

大于同一结构体字段

Field?validate:"gtfield=Field2"

gtefield

大于等于同一结构体字段

Field?validate:"gtefield=Field2"

ltfield

小于同一结构体字段

Field?validate:"ltfield=Field2"

ltefield

小于等于同一结构体字段

Field?validate:"ltefield=Field2"

eqcsfield

跨不同结构体字段相等

Struct1.Field?validate:"eqcsfield=Struct2.Field2"

necsfield

跨不同结构体字段不相等

Struct1.Field?validate:"necsfield=Struct2.Field2"

gtcsfield

大于跨不同结构体字段

Struct1.Field?validate:"gtcsfield=Struct2.Field2"

gtecsfield

大于等于跨不同结构体字段

Struct1.Field?validate:"gtecsfield=Struct2.Field2"

ltcsfield

小于跨不同结构体字段

Struct1.Field?validate:"ltcsfield=Struct2.Field2"

ltecsfield

小于等于跨不同结构体字段

Struct1.Field?validate:"ltecsfield=Struct2.Field2"

min

最大值

Field?validate:"min=1"

max

最小值

Field?validate:"max=2"

structonly

仅验证结构体,不验证任何结构体字段

Struct?validate:"structonly"

nostructlevel

不运行任何结构级别的验证

Struct?validate:"nostructlevel"

dive

向下延伸验证,多层向下需要多个dive标记

[][]string?validate:"gt=0,dive,len=1,dive,required"

dive Keys & EndKeys

与dive同时使用,用于对map对象的键的和值的验证,keys为键,endkeys为值

map[string]string?validate:"gt=0,dive,keys,eq=1|eq=2,endkeys,required"

required_with

其他字段其中一个不为空且当前字段不为空

Field?validate:"required_with=Field1 Field2"

required_with_all

其他所有字段不为空且当前字段不为空

Field?validate:"required_with_all=Field1 Field2"

required_without

其他字段其中一个为空且当前字段不为空

Field `validate:"required_without=Field1 Field2"

required_without_all

其他所有字段为空且当前字段不为空

Field?validate:"required_without_all=Field1 Field2"

isdefault

是默认值

Field?validate:"isdefault=0"

oneof

其中之一

Field?validate:"oneof=5 7 9"

containsfield

字段包含另一个字段

Field?validate:"containsfield=Field2"

excludesfield

字段不包含另一个字段

Field?validate:"excludesfield=Field2"

unique

是否唯一,通常用于切片或结构体

Field?validate:"unique"

alphanum

字符串值是否只包含 ASCII 字母数字字符

Field?validate:"alphanum"

alphaunicode

字符串值是否只包含 unicode 字符

Field?validate:"alphaunicode"

alphanumunicode

字符串值是否只包含 unicode 字母数字字符

Field?validate:"alphanumunicode"

numeric

字符串值是否包含基本的数值

Field?validate:"numeric"

hexadecimal

字符串值是否包含有效的十六进制

Field?validate:"hexadecimal"

hexcolor

字符串值是否包含有效的十六进制颜色

Field?validate:"hexcolor"

lowercase

符串值是否只包含小写字符

Field?validate:"lowercase"

uppercase

符串值是否只包含大写字符

Field?validate:"uppercase"

email

字符串值包含一个有效的电子邮件

Field?validate:"email"

json

字符串值是否为有效的 JSON

Field?validate:"json"

file

符串值是否包含有效的文件路径,以及该文件是否存在于计算机上

Field?validate:"file"

url

符串值是否包含有效的 url

Field?validate:"url"

uri

符串值是否包含有效的 uri

Field?validate:"uri"

base64

字符串值是否包含有效的 base64值

Field?validate:"base64"

contains

字符串值包含子字符串值

Field?validate:"contains=@"

containsany

字符串值包含子字符串值中的任何字符

Field?validate:"containsany=abc"

containsrune

字符串值包含提供的特殊符号值

Field?validate:"containsrune=?"

excludes

字符串值不包含子字符串值

Field?validate:"excludes=@"

excludesall

字符串值不包含任何子字符串值

Field?validate:"excludesall=abc"

excludesrune

字符串值不包含提供的特殊符号值

Field?validate:"containsrune=?"

startswith

字符串以提供的字符串值开始

Field?validate:"startswith=abc"

endswith

字符串以提供的字符串值结束

Field?validate:"endswith=abc"

ip

字符串值是否包含有效的 IP 地址

Field?validate:"ip"

ipv4

字符串值是否包含有效的 ipv4地址

Field?validate:"ipv4"

datetime

字符串值是否包含有效的 日期

Field?validate:"datetime"

5 注意事项

  • 当搜索条件与特殊标记冲突时,如:逗号(,),或操作(|),中横线(-)等则需要使用 UTF-8十六进制表示形式
type Test struct { 
    Field1 string `validate:"excludesall=|"` // 错误 
    Field2 string `validate:"excludesall=0x7C"` // 正确. 
}
  • 可通过validationErrors := errs.(validator.ValidationErrors)获取错误对象自定义返回响应错误
  • 自定义校验结果翻译
// 初始化翻译器
func validateInit() {
	zh_ch := zh.New()
	uni := ut.New(zh_ch)               // 万能翻译器,保存所有的语言环境和翻译数据
	Trans, _ = uni.GetTranslator("zh") // 翻译器
	Validate = validator.New()
	_ = zh_translations.RegisterDefaultTranslations(Validate, Trans)
	// 添加额外翻译
	_ = Validate.RegisterTranslation("required_without", Trans, func(ut ut.Translator) error {
		return ut.Add("required_without", "{0} 为必填字段!", true)
	}, func(ut ut.Translator, fe validator.FieldError) string {
		t, _ := ut.T("required_without", fe.Field())
		return t
	})
}

6 案例

6.1 HTTP案例

6.1.1 代码

package main

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

type RegisterRequest struct {
    Username string `json:"username" binding:"required"`
    Nickname string `json:"nickname" binding:"required"`
    Email    string `json:"email" binding:"required,email"`
    Password string `json:"password" binding:"required"`
    Age      uint8  `json:"age" binding:"gte=1,lte=120"`
}

func main() {
    router := gin.Default()
    router.POST("register", Register)
    router.Run(":9999")
}

func Register(c *gin.Context) {
    var r RegisterRequest
    err := c.ShouldBindJSON(&r)
    if err != nil {
        fmt.Println("register failed")
        c.JSON(http.StatusOK, gin.H{"msg": err.Error()})
         return
    }
    //验证 存储操作省略.....
    fmt.Println("register success")
    c.JSON(http.StatusOK, "successful")
}

6.1.2?测试

curl --location --request POST 'http://localhost:9999/register' \
--header 'Content-Type: application/json' \
--data-raw '{
    "username": "asong",
    "nickname": "golang梦工厂",
    "email": "7418.com",
    "password": "123",
    "age": 140
}'

6.1.3 返回结果

{
    "msg": "Key: 'RegisterRequest.Email' Error:Field validation for 'Email' failed on the 'email' tag\nKey: 'RegisterRequest.Age' Error:Field validation for 'Age' failed on the 'lte' tag"
}

看这个输出结果,可以看到validator的检验生效了,email字段不是一个合法邮箱,age字段超过了最大限制。

6.2 普通校验

package main
import (
   "fmt"
   "github.com/go-playground/validator/v10"
)
// 实例化验证对象
var validate = validator.New()
func main() {
   // 结构体验证
   type Inner struct {
      String string `validate:"contains=111"`
   }
   inner := &Inner{String: "11@"}
   errs := validate.Struct(inner)
   if errs != nil {
      fmt.Println(errs.Error())
   }
   // 变量验证
   m := map[string]string{"": "", "val3": "val3"}
   errs = validate.Var(m, "required,dive,keys,required,endkeys,required")
   if errs != nil {
      fmt.Println(errs.Error())
   }
}

?

?

文章来源:https://blog.csdn.net/ygq13572549874/article/details/135398051
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。