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 在设计时考虑了性能:

  1. 模式定义是静态的,可以重复使用
  2. 验证过程是惰性的,只在调用 Parse 时执行
  3. 提供了预编译模式选项
// 预编译模式以提高性能
compiledSchema, err := userSchema.Compile()
if err != nil {
    panic(err)
}

// 使用编译后的模式
result, err := compiledSchema.Parse(data)

总结

ZogZod 为 Golang 提供了强大的运行时值解析和验证能力,主要特点包括:

  • 直观的链式 API
  • 丰富的内置验证器
  • 详细的错误报告
  • 类型安全的解析结果
  • 支持自定义验证规则
  • 异步验证支持

对于需要处理复杂输入验证的 Golang 应用,ZogZod 是一个值得考虑的选择。

回到顶部