# 用户定义的关键字

¥User-defined keywords

你可以通过定义自己的关键字来扩展 Ajv 中可用的关键字。

¥You can extend keyword available in Ajv by defining your own keywords.

定义关键字的优点是:

¥The advantages of defining keywords are:

  • 允许创建无法使用预定义关键字表达的校验场景

    ¥allow creating validation scenarios that cannot be expressed using pre-defined keywords

  • 简化你的结构

    ¥simplify your schemas

  • 帮助将校验逻辑的更大部分引入到你的结构中

    ¥help bringing a bigger part of the validation logic to your schemas

  • 使你的结构更具表现力、更简洁、更贴近你的应用字段

    ¥make your schemas more expressive, less verbose and closer to your application domain

  • 实现修改数据的数据处理器(modifying 选项必须在关键字定义中使用)和/或在校验数据时产生副作用

    ¥implement data processors that modify your data (modifying option MUST be used in keyword definition) and/or create side effects while the data is being validated

如果关键字仅用于副作用并且其校验结果是预定义的,请在关键字定义中使用选项 valid: true/false 来简化生成的代码(在 valid: true 的情况下没有错误处理)和关键字函数(无需返回任何校验) 结果)。

¥If a keyword is used only for side-effects and its validation result is pre-defined, use option valid: true/false in keyword definition to simplify both generated code (no error handling in case of valid: true) and your keyword functions (no need to return any validation result).

用户定义的关键字使结构不可移植

当使用附加关键字扩展 JSON Schema 标准时,你需要注意几个潜在的问题:

¥When extending JSON Schema standard with additional keywords, you have several potential concerns to be aware of:

  • portability of your schemas - 它们只能与可以使用 Ajv 的 JavaScript 或 TypeScript 应用配合使用。

    ¥portability of your schemas - they would only work with JavaScript or TypeScript applications where you can use Ajv.

  • 维护结构所需的附加文档。

    ¥additional documentation required to maintain your schemas.

避免在 JTD 结构中使用非标准关键字

虽然可以为 JSON 类型定义模式定义其他关键字(这些关键字只能在模式的 metadata 成员中使用),但强烈建议不要这样做 - JTD 是专门为跨平台 API 设计的。

¥While it is possible to define additional keywords for JSON Type Definition schemas (these keywords can only be used in metadata member of the schema), it is strongly recommended not to do it - JTD is specifically designed for cross-platform APIs.

你可以使用 addKeyword 方法定义关键字。关键字在 ajv 实例级别定义 - 新实例将不会具有先前定义的关键字。

¥You can define keywords with addKeyword method. Keywords are defined on the ajv instance level - new instances will not have previously defined keywords.

Ajv 允许使用以下方式定义关键字:

¥Ajv allows defining keywords with:

  • 代码生成函数(所有预定义关键字均使用)

    ¥code generation function (used by all pre-defined keywords)

  • 校验功能

    ¥validation function

  • 编译功能

    ¥compilation function

  • 宏功能

    ¥macro function

例子。使用编译结构的 rangeexclusiveRange 关键字:

¥Example. range and exclusiveRange keywords using compiled schema:

ajv.addKeyword({
  keyword: "range",
  type: "number",
  schemaType: "array",
  implements: "exclusiveRange",
  compile: ([min, max], parentSchema) =>
    parentSchema.exclusiveRange === true
      ? (data) => data > min && data < max
      : (data) => data >= min && data <= max,
})

const schema = {range: [2, 4], exclusiveRange: true}
const validate = ajv.compile(schema)
console.log(validate(2.01)) // true
console.log(validate(3.99)) // true
console.log(validate(2)) // false
console.log(validate(4)) // false

ajv-keywords (opens new window) 包中定义了几个关键字(typeof、instanceof、range 和 propertyNames) - 它们可用于你的架构并作为你自己的关键字的起点。

¥Several keywords (typeof, instanceof, range and propertyNames) are defined in ajv-keywords (opens new window) package - they can be used for your schemas and as a starting point for your own keywords.

有关详细信息,请参阅 用户定义的关键字 参考。

¥See User-defined keywords reference for more details.