在写 Golang 的 WebServer 时我就很难受,缺一个类似 Node.js 的 joi 的框架,有很多想写的规则写不出来。
在 Golang 社区中参数校验一般是用 https://github.com/go-playground/validator 或者 https://github.com/astaxie/beego/tree/develop/validation 这些类似的东西。
我在使用这类框架的时候遇到了两个问题:
先给个 jio 的使用例子
package main
import (
"errors"
"io/ioutil"
"net/http"
"github.com/faceair/jio"
"github.com/go-chi/chi"
)
func main() {
r := chi.NewRouter()
r.Route("/people", func(r chi.Router) {
r.With(jio.ValidateBody(jio.Object().Keys(jio.K{
"name": jio.String().Transform(func(ctx *jio.Context) {
if ctx.Value != "faceair" {
ctx.Abort(errors.New("you are not faceair"))
}
}).Required(),
"age": jio.Number().Integer().Min(0).Max(100).Required(),
"phone": jio.String().Regex(`^1[34578]\d{9}$`).Required(),
}), jio.DefaultErrorHandler)).Post("/", func(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader( http.StatusOK)
w.Write(body)
})
})
http.ListenAndServe(":8080", r)
}
我是这么解决这些问题的。
同时 jio 还能给参数设置默认值、帮你做类型转换(string 转 array 转 int 等等)、能选择校验规则的顺序、能根据其他字段的数据选择不同的校验规则等等,我觉得 jio 灵活性比任何一个校验框架都要好(也包括 joi)。
更多的使用文档可以直接查看 https://github.com/faceair/jio/blob/master/README.zh.md 欢迎大家多多使用,可以给 star 鼓励,也可以给与一些反馈我好继续迭代改进。
1
Cbdy 2018-12-02 15:37:15 +08:00 via Android
|
2
blless 2018-12-02 17:22:54 +08:00 via Android
为啥不用 tag 啊
|
3
bubuhere 2018-12-02 17:41:40 +08:00 via iPhone 1
已 Star
|
5
zn 2018-12-02 18:31:42 +08:00 via iPhone
这语法太啰嗦了,无法想象。
|
6
blless 2018-12-02 18:34:03 +08:00 via Android
想了想我自己也写过一个,不过还是用 tag,不过我没有 required 这个关键字,只有一个 default,没有 default 就是 required,序列化没有直接传入对象指针 encode,用 fastjson 直接判断是否存在字段…
所以 1 不是问题,2 如果你的框架很多地方要检验同一个扩展规则,也是要另外放一个地方写的。所以这些问题我觉得都不是 tag 问题,而且目前参数检验框架的问题 |
7
loading 2018-12-02 18:46:04 +08:00 via Android
为啥这个 go 代码看起来这么恶心!!
|
8
faceair OP @blless #6 用 tag 可以解决 90% 的校验的问题吧。我可能是因为之前用过 joi 脑子里有些执念,另外还有一些骚操作想实现就自己重新造了一套。理性的说这些功能也不一定是人人都需要,比如:
1. 类型转换 字符串转布尔 字符串转数字 2. 根据其他字段选择校验规则 3. 业务层的逻辑校验用 Transform 也写进 jio 里,后面的业务逻辑里不用再关心数据对不对 🤔不过这些理论上有一部分也是可以自己写 parser 用 tag 实现,就是看到时候够不够像这么直观了。 只是一个轮子罢了,我自己可能有一些想法和思考,如果能碰上臭味相投的人就更好了 🤓 |
9
faceair OP 只是记得回复里不能用 markdown 贴代码,不过贴图上来以后这图片的大小处理也好恶心... 各位李姐万岁...
|
10
faceair OP @loading #7
@zn #5 https://gist.github.com/faceair/58c60e768edb464ad550cc7f39c2950f 这么写会好受一点吗?剩下的要是觉得 schema 的定义也很啰嗦的话,那我这里也没有更好的办法了,设计就是这样的了... |
11
reus 2018-12-02 21:50:18 +08:00
感觉太罗嗦了
|
12
Mitt 2018-12-04 01:19:11 +08:00 via iPhone
啰嗦但是有用,tag 是真的很难用,我一直想不通为什么要这么设计
|
13
layxy 2019-07-12 10:20:02 +08:00
go 上面没有一个好用的参数校验组件,都不能检查是 go 基本类型默认值还是调用者传的参数,有默认值的基本类型就没办法向调用者返回正确的错误信息,比如 A 调用 B 参数有一个布尔类型,该参数非必填,A 没有传该参数,B 接受反序列化结构体的时候该布尔类型会默认为 false,导致交互上的误导和错误,而且目前的校验框架是这样的,如果我传的参数和默认值一致也会认为我没传该参数,奇葩的逻辑和处理方式
|