两者的官网如下:
我这里准备了一些示例数据和获取数据的方法。接下来所有的操作都是基于这些数据来操作。
数据
{
"username": "月空人",
"email": "whbbit@prop.show",
"site": "https://www.prop.show",
"org": "PropShow",
"reading": [
{
"title": "Vue.js 设计与实现",
"author": "霍春阳",
},
{
"title": "Vue.js 设计与实现",
"author": "霍春阳",
},
],
}
{
"LOGIN_CONFIG": "{\"qqLogin\":2,\"wechatLogin\":true}",
}
获取数据的方法
import fs from 'node:fs/promises'
export const userData = await fs.readFile('./mockdata/user.json', 'utf-8')
.then(val => JSON.parse(val))
import fs from 'node:fs/promises'
export const configData = await fs.readFile('./mockdata/config.json', 'utf-8')
.then(val => JSON.parse(val))
基础的数据 Schema 的写法
import * as z from "zod";
import { userData } from "../api/user";
const UserSchema = z.object({
username: z.string(),
email: z.email(),
site: z.url(),
org: z.string(),
reading: z.array(
z.object({
title: z.string(),
author: z.string(),
}),
),
});
对数据的的校验
基础校验
UserSchema.parse(userData)
safeParse
这样书写后如果报错会抛出一个错误阻碍后续代码操作,它们都提供了一个 safeParse 的写法
const result = UserSchema.safeParse(userData);
if (!result.success) {
console.error(result.error);
}
else {
console.log(result.data);
}
美化错误输出
这时的错误是不太容易阅读的,它们也都提供了美化错误输出的写法
const result = UserSchema.safeParse(userData);
if (!result.success) {
console.error(z.flattenError(result.error));
}
else {
console.log(result.data);
}
自定义数据校验
它们提供的数据校验都很全了,但是有时我们需要一个自定义的规则,比如我这里需要 username 必须是纯中文的字符,这时我们该如何操作呢?
const UserSchema = z.object({
username: z.string().regex(/^[\u4E00-\u9FA5]+$/, { // [!code ++]
error: "用户名必须是中文", // [!code ++]
}), // [!code ++]
email: z.email(),
site: z.url(),
org: z.string(),
reading: z.array(
z.object({
title: z.string(),
author: z.string(),
}),
),
});
自动格式化数据
我们有时候需要对拿到的数据进行一些操作,我们可以在 Zod 和 Validate 中使用它们的 transform 来做。
下面的示例中,我们把 org 字符串转换为使用 - 连接。 PropShow -> prop-show
import { dash } from "radash";
const UserSchema = z.object({
username: z.string().regex(/^[\u4E00-\u9FA5]+$/, {
error: "用户名必须是中文",
}),
email: z.email(),
site: z.url(),
org: z.string().transform(val => dash(val)), // [!code ++]
reading: z.array(
z.object({
title: z.string(),
author: z.string(),
}),
),
});
对 JSON 字符串进行转换和校验
我们还会遇到的一个情况就是从数据库中读出一个 JONS 格式的字符串,我们在使用的时候大部分时候都需要将其转换为标准的 JavaScript 对象。我们如何对这个 JSON 格式的字符串进行校验和自动转换为标准的 JavaScript 对象呢?
在上面我们准备的数据中,configData 就是这样一个数据。它代表我们可以使用的第三方登录平台。
我们要做的事就是校验它是否是正确的包含 qqLogin 和 wechatLogin 的对象
const LoginConfigSchema = z.object({
qqLogin: z.boolean(),
wechatLogin: z.boolean(),
});
const LoginConfigStringSchema = z.object({
LOGIN_CONFIG: z
.string()
.transform(val => JSON.parse(val))
.pipe(LoginConfigSchema),
});
const result = LoginConfigStringSchema.safeParse(configData);
或者我们转过来,我们在调用接口的时候,有时候需要我们传递一个标准的 JSON 字符串,我们这时候也可以转过来,将 Object 自动转换为字符串
const configData = {
LOGIN_CONFIG: {
qqLogin: true,
wechatLogin: true
}
}
const LoginConfigStringSchema = z.object({
LOGIN_CONFIG: z.object({
qqLogin: z.boolean(),
wechatLogin: z.boolean(),
}).transform(val => JSON.parse(val))
});
const result = v.safeParse(LoginConfigStringSchema, configData);
console.log(result.data)
// 输出结果
// {
// LOGIN_CONFIG: "{\"qqLogin\":true,\"wechatLogin\":true}",
// }
中文错误的支持 —— i18n
在 Zod 中我们可以直接使用 z.config(z.locales.zhCN()) 来配置,在 Valibot 中使用 v.setGlobalConfig({ lang: 'zh-CN' }) 进行配置。
Valibot 你需要安装并引入
@valibot/i18n
JSON Schema
在 Zod 中你可以直接使用 z.toJSONSchema(LoginConfigStringSchema);在 Valibot 中你需要安装 @valibot/to-json-schema,使用方式为 v.safeParse(LoginConfigStringSchema, configData)
整体比较
| 比较项 | Zod | Valibot |
|---|---|---|
| 写法 | 链式操作 | 函数组合 |
| 大小 | 268.3k | 本体大小 80.4k, @valibot/to-json-schema 大小为 8.4k, @valibot/i18n/zh-CN 大小为 8.2k |
