golang运行时值解析与验证的schema构建插件库ZogZod的使用
Golang运行时值解析与验证的schema构建插件库ZogZod的使用
Zog是一个类似Zod和Yup的Go语言schema解析器和验证器,用于运行时值解析和验证。它允许你定义schema,转换值以匹配,断言现有值的形状,或两者兼而有之。
主要特性
- 简洁而富有表现力的schema接口,能够建模简单到复杂的数据模型
- 类似Zod的API,使用方法链以类型安全的方式构建schema
- 可扩展:添加你自己的测试和schema
- 丰富的错误信息,带有详细的上下文,使调试变得轻松
- 快速:Zog是最快的Go验证库之一
- 内置对大多数类型的强制转换支持
- 零依赖!
- 四个辅助包:zenv、zhttp、zjson和i18n
安装
go get github.com/Oudwins/zog
使用示例
1. 创建用户schema和结构体
import (
z "github.com/Oudwins/zog"
)
type User struct {
Name string
Age int
}
var userSchema = z.Struct(z.Shape{
// 非常重要:schema键如"name"必须匹配结构体字段名,而不是输入数据
"name": z.String().Min(3, z.Message("覆盖默认消息")).Max(10),
"age": z.Int().GT(18),
})
2. 验证你的schema
使用schema.Parse()
func main() {
u := User{}
m := map[string]string{
"name": "Zog",
"age": "", // 不会返回错误,因为默认情况下字段是可选的
}
errsMap := userSchema.Parse(m, &u)
if errsMap != nil {
// 处理错误 -> 参见错误部分
}
u.Name // "Zog"
// 注意这看起来可能有点奇怪,但我们没有说age是必需的,所以Zog只是跳过了空字符串
// 如果我们希望0是age的有效值,可以使用指向int的指针,如果输入数据中没有该值,则为nil
u.Age // 0
}
使用schema.Validate()
func main() {
u := User{
Name: "Zog",
Age: 0, // 不会返回错误,因为默认情况下字段是可选的,否则会报错
}
errsMap := userSchema.Validate(&u)
if errsMap != nil {
// 处理错误 -> 参见错误部分
}
}
3. 与HTTP和JSON一起使用
使用zhttp包
import (
zhttp "github.com/Oudwins/zog/zhttp"
)
err := userSchema.Parse(zhttp.Request(r), &user)
使用zjson包
import (
zjson "github.com/Oudwins/zog/zjson"
)
err := userSchema.Parse(zjson.Decode(bytes.NewReader(jsonBytes)), &user)
4. 验证环境变量
import (
zenv "github.com/Oudwins/zog/zenv"
)
err := envSchema.Parse(zenv.NewDataProvider(), &envs)
5. 解析单个字段
var t = time.Time
errsList := Time().Required().Parse("2020-01-01T00:00:00Z", &t)
6. 无限制地转换数据
var dest []string
schema := z.Preprocess(func(data any, ctx z.Ctx) ([]string, error) {
s := data.(string) // 不要这样做,实际应该检查类型
return strings.Split(s, ","), nil
}, z.Slice(z.String().Trim().Email().Required()))
errs := schema.Parse("foo@bar.com,bar@foo.com", &dest) // dest = [foo@bar.com bar@foo.com]
项目状态
- 在达到v1.0.0之前,API可能会发生变化
- 最有可能发生变化的是数据提供者API
- 尽管我们希望将破坏性变更保持在最低限度,但Zog仍处于0版本,将根据semver在次要版本中进行破坏性变更
路线图
- 支持schema.Clone()
- 支持structs和slices的catch和default
- 从schema生成结构体
许可证
该项目使用MIT许可证 - 详情请参见LICENSE文件。
更多关于golang运行时值解析与验证的schema构建插件库ZogZod的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang运行时值解析与验证的schema构建插件库ZogZod的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang 运行时值解析与验证库 ZogZod 使用指南
ZogZod 是一个受 TypeScript 的 Zod 库启发的 Golang 运行时值解析与验证库,它提供了简洁的 API 来定义数据模式并进行验证。
安装
go get github.com/go-zoz/zog
基本用法
1. 定义模式
import "github.com/go-zoz/zog"
// 定义一个用户模式
userSchema := zog.Object{
"name": zog.String().Min(3).Max(50),
"age": zog.Number().Min(18).Max(120),
"email": zog.String().Email(),
"isAdmin": zog.Boolean().Optional(),
"address": zog.Object{
"street": zog.String(),
"city": zog.String(),
},
}
2. 解析和验证数据
data := map[string]interface{}{
"name": "John Doe",
"age": 30,
"email": "john@example.com",
"address": map[string]interface{}{
"street": "123 Main St",
"city": "New York",
},
}
result, err := userSchema.Parse(data)
if err != nil {
// 处理验证错误
fmt.Println("Validation error:", err)
return
}
// 使用解析后的数据
fmt.Printf("Valid user: %+v\n", result)
高级特性
1. 自定义验证器
passwordSchema := zog.String().
Min(8).
Max(50).
Regex(`[A-Z]`, "must contain at least one uppercase letter").
Regex(`[0-9]`, "must contain at least one number")
// 使用
_, err := passwordSchema.Parse("weakpassword")
if err != nil {
fmt.Println(err) // 会显示自定义错误消息
}
2. 转换数据
// 定义一个转换器,将字符串转换为整数
toIntSchema := zog.String().Transform(func(s string) (interface{}, error) {
return strconv.Atoi(s)
})
value, _ := toIntSchema.Parse("42")
fmt.Printf("%T %v\n", value, value) // int 42
3. 联合类型
idSchema := zog.Union(
zog.String().UUID(),
zog.Number().Int(),
)
_, err1 := idSchema.Parse("550e8400-e29b-41d4-a716-446655440000") // UUID
_, err2 := idSchema.Parse(12345) // 数字
4. 数组验证
tagsSchema := zog.Array(zog.String().Min(2).Max(20)).Max(5)
_, err := tagsSchema.Parse([]string{"go", "programming", "backend"})
if err != nil {
fmt.Println(err)
}
5. 异步验证
// 定义一个异步验证器,检查用户名是否唯一
usernameSchema := zog.String().
Min(3).
Max(20).
Async(func(s string) error {
// 模拟异步检查
time.Sleep(100 * time.Millisecond)
if s == "takenusername" {
return fmt.Errorf("username already taken")
}
return nil
})
err := usernameSchema.ParseAsync("takenusername").Await()
if err != nil {
fmt.Println(err)
}
错误处理
ZogZod 提供了详细的错误信息:
_, err := userSchema.Parse(map[string]interface{}{
"name": "Jo", // 太短
"age": 17, // 小于18
"email": "invalid",
})
if err != nil {
if validationErr, ok := err.(zog.ValidationError); ok {
for _, issue := range validationErr.Issues {
fmt.Printf("Field %s: %s (code: %s)\n",
issue.Path, issue.Message, issue.Code)
}
}
}
性能考虑
ZogZod 在设计时考虑了性能:
- 模式定义是静态的,可以重复使用
- 验证过程是惰性的,只在调用 Parse 时执行
- 提供了预编译模式选项
// 预编译模式以提高性能
compiledSchema, err := userSchema.Compile()
if err != nil {
panic(err)
}
// 使用编译后的模式
result, err := compiledSchema.Parse(data)
总结
ZogZod 为 Golang 提供了强大的运行时值解析和验证能力,主要特点包括:
- 直观的链式 API
- 丰富的内置验证器
- 详细的错误报告
- 类型安全的解析结果
- 支持自定义验证规则
- 异步验证支持
对于需要处理复杂输入验证的 Golang 应用,ZogZod 是一个值得考虑的选择。