2022 年 5 月 16 日,星期一 ·7分钟阅读

在 Node.js 中开始使用 JSON Schema

原文发表于 simonplend.com

为您的 Node.js 应用程序构建请求验证的第一步是找到一种方法来创建灵活的验证规则。当您尝试选择一个验证库来使用时,这通常比您预期的要困难。它们彼此都不同,而且不清楚一个库比另一个库有什么好处。

也许您之前尝试过构建自己的自定义验证,但它开始变得混乱且难以维护。您想建立一些可靠的验证,然后继续在应用程序中构建令人兴奋的新功能。为什么添加验证是如此头痛?!

在这篇文章中,我们将学习 JSON Schema 规范如何帮助我们创建灵活的验证规则。我们将编写一个模式来描述我们期望数据采用何种格式,然后我们将编写一些使用 Ajv 验证库来根据它验证我们的数据的 JavaScript。

让我们开始吧!

强大的验证组合

JSON Schema 规范 定义了一种基于 JSON 的格式来描述 JSON 数据的结构。这包括验证关键字,例如 typerequiredproperties。这些关键字使我们能够创建一个对我们期望数据采用的格式的定义。这被称为“模式”。它可以像这样简单:

模式
{ "type": "string" }

要根据模式验证数据,我们需要使用一个实现 JSON Schema 规范的验证库。 Ajv(另一个 JSON Schema 验证器) 库是客户端和服务器端 JavaScript 最流行的 JSON Schema 验证器,每周从 npm 下载超过 5000 万次

让我们动手实践,看看使用 JSON Schema 和 Ajv 验证数据是什么样的。

要了解有关 JSON Schema 的更详细介绍,请查看博客文章 JSON Schema 在 5 分钟内

创建模式和验证数据

首先,我们需要运行命令 npm install ajv 来安装 Ajv 库。

然后,我们可以直接进入定义 JSON 模式。它描述了我们期望的结构和类型

1const iceCreamSchema = {
2  type: "object",
3  properties: {
4    flavour: { type: "string" },
5    price: { type: "number" },
6    stock: { type: "number" },
7  },
8  required: ["flavour", "price", "stock"],
9};

现在,我们将定义我们想要验证的数据

1const iceCreamData = {
2  flavour: "Pistachio",
3  price: 1.99,
4  stock: null,
5};

然后,我们将导入 Ajv 库并创建一个新的 Ajv 实例

1import Ajv from "ajv";
2
3const ajv = new Ajv();

并用它来根据我们的模式验证数据

1const isDataValid = ajv.validate(iceCreamSchema, iceCreamData);

最后,我们将添加一些代码来处理验证结果

1if (isDataValid) {
2  console.log("The ice cream data is valid! 🍨");
3} else {
4  console.error("The ice cream data is invalid:", ajv.errors);
5}

当我们把这段代码组合在一起并运行它时,我们将获得以下输出

1The ice cream data is invalid: [
2  {
3    instancePath: '/stock',
4    schemaPath: '#/properties/stock/type',
5    keyword: 'type',
6    params: { type: 'number' },
7    message: 'must be number'
8  }
9]

很不错吧?

好吧,我们已经创建了一个描述我们期望的结构和类型的模式,验证了根据它的数据,并处理了任何验证错误。到目前为止还不错!

编辑提醒:在 AJV 的最新主要版本中,引入了“严格模式”,默认情况下启用,这在使用有效的 JSON 模式时有时会抛出异常。如果您遇到与严格模式相关的错误,请查看 文档,了解有关如何禁用它或特定规则的详细信息。我们认为这可能更适合作为 linter 功能,但它确实有助于防止模式编写中的意外错误。- Ben Hutton

作为最后一步,我们将看看如何改进创建 JSON 模式的过程。

模式生成

JSON 模式是定义验证规则的一种富有表现力的方式,但有时手动编写模式会比较麻烦。有一个名为 fluent-json-schema 的方便库,可以帮助我们生成 JSON 模式。让我们试一试。

请注意,虽然使用工具来定义要转换为 JSON 模式的验证规则可以使您拥有控制权,但其他生成 JSON 模式的方案(例如从实例数据生成)通常会让您得到一个部分完成或有时不正确的 JSON 模式。其他方法可能更适合称为“搭建”而不是“生成”,因为您将拥有基本内容,但仍需要进行一些工作才能使它完整且可用。

首先,我们需要通过运行命令 npm install fluent-json-schema 来安装库。然后,我们可以导入它并用它来生成我们的模式

1import S from "fluent-json-schema";
2
3const iceCreamSchema = S.object()
4  .prop("flavour", S.string().required())
5  .prop("price", S.number().required())
6  .prop("stock", S.number().required())
7  // This method call returns the generated schema as an object.
8  .valueOf();

如果我们 console.log iceCreamSchema 对象,我们可以看到我们生成的 JSON 模式

模式
{ "$schema": "https://json-schema.fullstack.org.cn/draft-07/schema#", "type": "object", "properties": { "flavour": { "type": "string" }, "price": { "type": "number" }, "stock": { "type": "number" } }, "required": ["flavour", "price", "stock"]}

你会注意到,这个生成的模式几乎与我们之前“手动”编写的 iceCreamSchema 相同。我们可以用这个生成的模式替换我们手工制作的模式,验证将与之前一样。

如果我们在 TypeScript 中编写应用程序,TypeBox 库是 fluent-json-schema 的一个很好的替代方案。

模式生成取决于个人喜好:有些人喜欢“手动”编写原始 JSON 模式,而另一些人更喜欢使用帮助生成它们的库。尝试一下这两种方法,选择最适合你的方法。

自己试试

总结

我们可以将 Ajv 用作独立库,也可以将其集成到我们用来构建 Node.js 应用程序的框架中。一些 Node.js 框架甚至提供基于 JSON 模式的验证,Ajv 内置

当我们将 JSON 模式和 Ajv 结合起来时,我们拥有一个灵活的解决方案,可以在我们的 Node.js 应用程序中实现验证。

  • 学一次,处处可用。JSON 模式规范是跨平台的,并且每个流行的编程语言都有 验证库。我们没有被锁定在某个库、框架或语言中。一旦我们学习了 JSON 模式的基本原理,我们就可以在任何地方使用它。
  • 可移植性。由于 JSON 模式是跨平台的,即使我们决定用另一个框架或语言重写我们的应用程序,我们也可以带上我们的模式。
  • 速度。在幕后,Ajv 将我们的 JSON 模式编译成 JavaScript 代码。这提高了对模式进行重复数据验证的性能。例如,当我们的 Node.js 应用程序启动时,可以由 Ajv 编译模式。应用程序接收的 HTTP 请求数据随后可以根据预编译的模式进行验证。
  • 活跃且支持的社区。Slack 上有一个活跃的社区,他们很乐意提供帮助(JSON 模式网站 有一个你可以用来加入的链接)。

进一步阅读

如果你想了解更多关于 JSON 模式的知识,你可能会发现这些链接很有帮助

  • 如何在 Express API 中处理请求验证。如果你使用的是 Express Node.js 框架,我编写了这篇指南来帮助你将 Ajv 库集成到你的应用程序中。
  • Fastify 框架验证文档。Fastify Node.js 框架集成了 Ajv 库,使得用 JSON 模式添加验证变得简单直接。
  • 理解 JSON Schema。这是一本免费的在线书籍,将教你 JSON Schema 的基础知识。也可以以 PDF 格式下载以供离线阅读。
  • JSON Schema 速查表。我创建了这份速查表 PDF,作为 JSON Schema 验证关键字的便捷参考。无论何时编写模式,它都能帮助您。

图片来自 Manik RatheeUnsplash 上。