• 欢迎来到本博客,希望可以y一起学习与分享

Gin参数验证Validator/校验规则/json数组/判断空值还是没传

笔记 benz 2年前 (2021-05-14) 294次浏览 0个评论 扫描二维码
文章目录[隐藏]

gin 的参数校验

gin 使用了 go-playground/validator库, 使用tag声明的方式, 支持http请求request中的各类校验

使用方法

1. 校验参数定义

校验参数是定义在结构体上的,因此在首先需要定义好接受数据的结构体,再定义每个属性的校验参数:

结构体字段 binding tag的内容就是校验参数。

2. 数据绑定

gin中提供了常用的 ShouldBindWith/ShouldBindUri方法,来实现自动的数据与结构体的绑定,提供了以下类型的数据:

数据类型 Tag Context-Type 数据源 使用示例
JSON json application/json Body ShouldBindWith(&data, binding.Query)
XML xml application/xml、text/xml Body ShouldBindWith(&data, binding.XML)
Form form application/x-www-form-urlencoded Body c.ShouldBindWith(&data, binding.Form)
Query form url query ShouldBindWith(&data, binding.Query)
FormPost form application/x-www-form-urlencoded Body ShouldBindWith(&data, binding.FormPost)
FormMultipart form multipart/form-data Body ShouldBindWith(&data, binding.FormMultipart)
ProtoBuf application/x-protobuf Body ShouldBindWith(&data, binding.ProtoBuf)
MsgPack application/x-msgpack、application/msgpack Body ShouldBindWith(&data, binding.MsgPack)
YAML application/x-yaml Body ShouldBindWith(&data, binding.YAML)
Uri uri uri ShouldBindUri(&data)
Header header Header ShouldBindWith(&forwardRule, binding.Header)

说明

数据类型:指的是传输的数据类型

Tag:结构体定义的Tag,揭示了数据字段与结构体字段的对应关系,如:Form类型数据中 id对应结构体中的ID字段,那么就需要定义一下内容:

Context-Type:HTTP中的Header 字段之一,表示Body的数据类型,gin.Context中的Bind方法会根据Content-Type自动绑定数据到对应类型上

数据源:指的是从哪里取数据,Body指的是从HTTP Body中获取数据,url query指从URL的quey参数中获取数据,url指的是从url中获取参数,如:/api/v1/xxx/:id,id参数就是从url中来获取的。

使用示例:使用的例程

3. 校验结果获取

ShouldBindWith会返回error信息,如果error信息不为空,则表明出现错误,错误信息就包含在error中,如果error为空,则表明校验通过,示例如下:

校验规则

完整的校验规则可参考https://godoc.org/github.com/go-playground/validator,下面分享常用的校验规则规则:

数字值限制

注:如果限制之间存在冲突,如 eq=10,ne=10,则会根据先后顺序,后面的会覆盖前面的定义,以后面定义的为准;校验内容为eq=10,ne=10,只会生效ne=10,如果存在冲突,所有校验规则均符合此规律。

限制范围

限制值

字符串长度限制

限制长度范围

限制值内容

存在性校验

注:这里需要特别注意的是,这里是否存在是根据0值与非0值判断的,如果字段中传了对应的0值,也会被认为是不存在的

必选

可选

如果存在,则继续向后校验规则xxx=xxx,如果不存在,则xxx=xxx不生效,但是如果omitempty之前存在校验规则,则前面的校验规则还是生效的,如 gte=-1,omitempty,len=3,则gte=-1规则始终生效,而len=3只有在值不为0时生效。
关联校验

结构体字段间校验

一个层级内部校验

多个层级之间校验

注:此处要注意的是,多个结构体之间的校验必须是字段之间存在层级联系,且只能是上层的与下层的做关联,不能反过来,如下:

dive 对数组校验

dive 的意思是潜水,潜水也就是深入到水下,dive在这里的意思是也差不多,就是更深入一层的意思,如当前字段类型是 []string,那么深入一层,就从 整体(array) 到 局部(array中的一个元素),对应到校验上,就是dive前是对整体校验,dive后是对整体中的元素校验。示例:

一般数组

检验内容:[]string长度必须大于0,数组中元素string长度必须在1-100之间。

结构体数组校验

虽然这里dive前后未定义相关校验规则,但是如果要启用 AStruct 中定义的校验规则,那么dive是必须的,否则AStruct中定义的规则不会生效。

dive对Map校验

dive的含义在这里仍然类似于数组,整体 -> 局部 的规则不变,但是map的特殊性在于不仅有value值,还有key值,这里就需要方法去区分是校验value,还是校验key;这里使用了 keys 和 endkeys来标记key值的校验范围,从keys开始,至endkeys结束。

校验内容:未对整体做校验,限制key值长度必须在1-100之间,value值的长度也必须在1-100之间

structonly

当一个结构体定义了校验规则,但是在某些地方,不需要这些校验规则生效的时候,可以使用structonly标记,存在此标记的结构体内部的校验规则将不会再生效。如下:

结构体Timeout各个字段定义了校验内容,但是我在MyStructTimeout字段使用了structonly标记,那么Timeout中定义的校验内容将不再生效。

nostructlevel

nostructlevel 类似于structonly,唯一不同之处是要想忽略规则的效果生效,必须要使用required或 omitempty

忽略校验规则

多校验规则“或”运算

ShouldBind与Bind方法的区别

Gin参数验证shouldbind/Bind区别及多次绑定 request body

几种常用参数校验

 get 参数

来源:gin: Only Bind Query String

curl -X GET “localhost:8085/testing?name=eason&address=xyz”

 路径参数

来源:gin: Bind Uri

curl -v localhost:8088/thinkerou/987fbc97-4bed-5078-9f07-9141ba07c9f3

json body

来源:gin: Model binding and validation

header

来源:gin: Bind Header

curl -H “rate:300” -H “domain:music” 127.0.0.1:8080/

json body是一个对象数组

ShouldBindJSON并不会校验对象数组中的每个对象是否符合要求, 需要自行调用方法处理

可以抽象出一个通用的函数

使用时

更友好的错误提示

当validation报错的时候, 我们期望得到一个更友好的提示信息, 便于使用者确认问题

参考:

  1. https://github.com/gin-gonic/gin/issues/430
  2. https://medium.com/@seb.nyberg/better-validation-errors-in-go-gin-88f983564a3d

以下是一种实现, 处理的常用的 validation 规则的错误展示

判断: 空值还是没有传递

有些场景, 如果一个json对象中, 某个字段可以为空, 但是非空的时候, 要执行某些特殊的逻辑

此时, 使用默认的validation是无法判断, 请求中没有这个字段, 还是传了空值:

其他

自定义错误类型/信息

参考

Go: gin validation
Gin请求参数校验


文章 Gin参数验证Validator/校验规则/json数组/判断空值还是没传 转载需要注明出处
喜欢 (0)

您必须 登录 才能发表评论!