• 前端中如何使用Zod验证前端数据的合法性
  • 发布于 2个月前
  • 363 热度
    0 评论
数据验证可能是一项艰巨的任务,特别是当处理来自不同来源、结构和格式未知的数据时。确保来自表单、API或其他第三方来源的数据符合我们在应用程序中定义的模式非常重要。数据验证在任何应用程序开发中都是必不可少的,因为它确保我们接收到的数据的准确性和完整性。

数据验证的重要性原因:
1.通过确保在我们的应用程序中输入的数据正确且格式正确,以防止错误发生。
2.通过防止可能危害我们应用程序安全的恶意输入,提升我们系统的安全性。
3.通过确保我们允许的数据准确可靠,以便更容易生成有用的洞察力,从而促进数据分析。
然而,如果没有正确的工具,数据验证可能会非常具有挑战性。

什么是Zod
Zod是一个以TypeScript为主的模式声明和验证库。我使用术语“模式”来广泛指代任何数据类型,从简单的字符串到复杂的嵌套对象。Zod允许您声明任何类型的数据模式,并以类型安全的方式验证数据。一旦您定义了验证器,Zod可以自动推断出静态TypeScript类型。与TypeScript不同,TypeScript在编译时执行类型检查,而Zod提供运行时类型检查,为我们提供了额外的类型安全层。

使用Zod进行数据验证的潜在好处:
1.类型安全。它使您能够以更类型安全的方式定义数据,从而可以产生更健壮和可靠的代码。
2.易于使用。Zod的API使用可链接的接口(例如z.string().min(20).nonempty())来定义和验证数据模式,简单直观。
3.可定制性。Zod允许我们创建自定义错误消息和其他验证选项,如数据转换和条件验证。
性能和开发者体验(DX)。以速度和效率为核心,Zod提供了友好的开发者体验,得益于其简单直观的API。

使用Zod验证数据
在本节中,我们将探讨如何使用zod来定义和验证各种数据类型。以下示例展示了我们如何通过API从前端接收数据,并根据我们定义的zod数据模式对其进行验证。

下面的代码展示了一个处理用户登录的Express API:
import { Request, Response, Router } from "express";
import { z } from "zod";
const router = Router();
const userSchema = z.object({
  email: z.string().email().nonempty(),
  password: z.string().min(8).nonempty(),
});

function signIn(req: Request, res: Response) {
  const { email, password } = req.body;

  try {
    // 堆代码 duidaima.com
    // Validate the incoming data against the userSchema
    userSchema.parse({ email, password });
    // If validation passes, further validate against data in db
  } catch (error) {
    // If validation fails, handle the error
    res.status(400).json({
      error: error,
    });
  }
}

// Routes
router.post("/signin", signIn);

export default router;
在上面的代码中,我们使用zod库定义了一个userSchema对象,该对象具有email和password属性。然后,我们添加了一些验证规则,例如.string().email().nonempty(),我们可以在以后使用这些规则来验证用户提供的数据。需要注意的是,.email()方法只检查基本的电子邮件格式,并不会对包含可打印字符、带引号的本地部分或者包含表情符号的电子邮件标记错误。

使用 zod 模式,.parse 方法会根据定义的模式验证提供的数据。如果验证成功,zod 将返回一个带有完整类型信息的数据的深层克隆。如果验证失败,zod 将抛出一个错误。

当我们想要优雅地处理验证错误,而不让zod抛出错误时,我们可以在模式上使用.safeParse方法。该方法返回一个对象,其中success属性设置为布尔值,data属性包含解析后的数据(如果验证成功),error属性包含验证错误(如果验证失败)。
import { Request, Response, Router } from "express";
import { z } from "zod";

const router = Router();

const userSchema = z.object({
  email: z.string().email().nonempty(),
  password: z.string().min(8).nonempty(),
});

function signIn(req: Request, res: Response) {
  const { email, password } = req.body;

  // Validate the incoming data against the userSchema
  const result = userSchema.safeParse({ email, password });

  if (!result.success) {
    // If validation fails, handle the error
    res.status(400).json({
      error: result.error,
    });
    return;
  }

  // zod validation passed, further validate against data values in db

}

// Routes
router.post("/signin", signIn);

export default router;
如果您需要执行异步验证,可以使用.parseAsync和.safeParseAsync方法。

Zod功能架构
Zod还允许您定义和验证从函数传递的输入和返回的输出。您可以在Zod中定义函数模式,如下所示
z.function(args, returnType)
它接受两个参数,第一个是输入参数,第二个参数是你期望从函数中返回的函数返回类型。返回类型可以是一个由zod定义的数据模式。
const signInSchema = z.function(z.object({
  body: z.object({
    email: z.string().email().nonempty(),
    password: z.string().min(8).nonempty(),
  })
}), z.undefined());

// Usage example
const req = { body: { email: "example@example.com", password: "password" } };
const res = { status: (code: number) => ({ json: (data: any) => console.log(code, data) }) };

const result = signInSchema.safeParse(signIn);
if (result.success) {
  result.data(req, res);
} else {
  console.error(result.error);
}
Zod函数模式有两个参数:输入模式和输出模式。在这种情况下,输入模式是一个具有body属性的对象,该属性具有电子邮件和密码字段。由于该函数不返回任何内容,因此输出模式未定义。

使用signInSchema,我们可以调用signInSchema.safeParse(signIn)并检查结果的success属性。如果为true,我们可以使用结果的data属性调用请求和响应对象。如果为false,我们可以使用结果的error属性处理错误。

类型强制
Zod在验证过程中提供了内置的强制转换功能,可以自动将输入数据转换为所需的数据类型。这对于需要验证来自外部来源的数据,并确保其与预期的格式或数据类型匹配的情况非常有用。

这是在Zod中使用强制的一个例子:
const { z } = require("zod");

const schema = z.object({
  name: z.string(),
  age: z.number().optional().transform((value) => {
    if (typeof value === "string") {
      return parseInt(value, 10);
    }
    return value;
  }),
});

const input = { name: "John", age: "20" };
const validatedData = schema.parse(input);

console.log(validatedData);
// Output: { name: "John", age: 20 }
在这个例子中,年龄字段是可选的,并且被定义为一个数字。我们使用转换方法将输入值强制转换为数字,如果它以字符串形式提供。如果输入值已经是一个数字,该函数将直接返回它。

请注意,虽然强制转换在某些情况下可能很有用,但它也可能引入意外行为和潜在的错误。您应该谨慎使用强制转换,并确保它适用于您的使用情况。

以下是您可能更喜欢Zod而不是Joi和Yup的一些潜在原因:
1. Zod是一个相对较新的库(首次发布于2020年),旨在提供更现代化和用户友好的模式验证方法。它具有简单直观的API,旨在易于使用和理解。
2. Zod支持同步和异步验证,这在某些情况下非常有用,例如您需要验证从API或数据库检索的数据。
3. Zod对类型安全性非常重视,并且提供了对TypeScript类型的内置支持。如果您的项目已经在使用TypeScript,这将特别有帮助。
4. Zod非常可定制和可扩展,允许您定义自定义验证规则和错误消息,以适应您的特定需求。

结束
数据验证是任何应用程序开发中的重要组成部分,它确保我们接收到的数据的准确性和完整性。然而,如果没有正确的工具,数据验证可能是一项具有挑战性的任务。Zod 提供了一个以 TypeScript 为主的模式声明和验证库,允许我们以类型安全的方式定义任何类型的数据模式,并对数据进行验证。

通过其类型安全性、易用性、可定制性和开发者体验,Zod在数据验证方面能够提供显著的好处。通过在应用程序中使用Zod实现验证,您可以使数据验证过程更加健壮、可靠和高效。
用户评论