返回介绍

首页

发布于 2024-08-14 01:17:13 字数 26747 浏览 0 评论 0 收藏 0

安装

npm install ajv

开始

您可以在 这里 调试看看。

做最快速的验证:

// Node.js require:
var Ajv = require('ajv');
// 或是 ESM/TypeScript import
import Ajv from 'ajv';

var ajv = new Ajv(); // 可以传入配置项, 例如: {allErrors: true}
var validate = ajv.compile(schema);
var valid = validate(data);
if (!valid) console.log(validate.errors);

用最少的代码:

// ...
var valid = ajv.validate(schema, data);
if (!valid) console.log(ajv.errors);
// ...

或者

// ...
var valid = ajv.addSchema(schema, 'mySchema')
               .validate('mySchema', data);
if (!valid) console.log(ajv.errorsText());
// ...

Ajv 将 schema 编译为函数并在所有情况下对其进行缓存(使用 fast-json-stable-stringify 对 schema 进行序列化,或是自定义函数为键),这样下次使用相同的 schema 时(不一定是相同的对象实例) 时,就不会再次编译。

使用 compilegetSchema 方法(不需要额外调用其他函数) 返回的已编译函数可以获得最佳性能。

::: warning 请注意 每次调用验证函数或 ajv.validate 时都会覆盖 errors 属性。如果你想之后再使用它(比如说在回调函数中),您需要将 errors 数组赋值给另一个变量。 :::

::: tip TypeScript ajv 提供了开箱即用的 TypeScript 声明。因此您无需安装已经弃用的 @types/ajv 模块。 :::

在浏览器中使用

如果需要在几个包中使用 Ajv,可以使用 npm run bundle 创建一个单独的 UMD 包。

您可以直接在浏览器中加载 Ajv.

<script src="ajv.min.js"></script>

这个包可以用于不同的模块系统,如果没有找到则会创建全局变量 Ajv

浏览器包可以在 CDN 找到

::: warning 注意 一些框架,例如 Dojo,可能会重新定义全局引入,这种方式与 CommonJS 模块格式是不兼容的。在这种情况下,必须先加载 Ajv 包,然后才能使用全局 Ajv。 :::

Ajv 和 内容安全策略(CSP)

如果您正在使用 Ajv 在浏览器文档中编译一个 schema (这是典型用法),但是它配置了内容安全策略(CSP, Content Security Policy),该策略需要 script-src 指令且包含了 unsafe-eval 值。 注意: ⚠️, unsafe-eval 值并不是一个安全的策略。因为它有可能打开文档的跨站脚本攻击。

为了在不影响 CSP 的情况下使用 Ajv,您可以 使用 CLI 对 schema 进行预编译 。这将把 schema JSON 转换为 JavaScript 文件,该文件会导出一个 validate 函数到运行时编译的模式中。

需要注意的是预编译使用的是 ajv-pack 进行的,它可以编译的模式特性有一些限制。成功的预编译应该和运行时编译的 schema 是相同的。

命令行接口

ajv-cli 可以作为单独的 npm 包。它支持如下功能:

  • 编译 JSON Schema 以测试其有效性。
  • BETA:生成独立模块,导出不需要 Ajv 使用的验证函数(使用 ajv-pack )。
  • 将 schema 迁移到 draft-07 (采用 json-schema-migrate )
  • 根据 JSON Schema 验证文件。
  • 根据 JSON Schema 测试数据的期望有效性。
  • 引用的 schema。
  • 自定义 meta-schema。
  • JSON、JSON5、YAML 和 JavaScript 格式的文件。
  • 所有的 Ajv 配置项。
  • 报告 JSON-patch 格式验证后的数据更改。

验证关键字 (看左边目录的验证那里)

注释关键字

JSON Schema 规范定义了几个描述 schema 本身但不会触发验证的注释关键字。

  • titledescription :表示该 schema 数据代表的信息。
  • $comment :(draft-07 新增)。给开发人员的信息。通过设置 $comment 项,Ajv 可以记录或将注释字符串传递给用户提供的函数。
  • default :数据实例的默认值。
  • examples :(draft-06 新增)数据实例的数组。 Ajv 不会根据 schema 检查这些实例的有效性。
  • readOnlywriteOnly :(draft-07 新增) 根据数据源(数据库、api 等) 将数据实例标记为只读或只写。
  • contentEncodingRFC 2045 。如:"base64"。
  • contentMediaTypeRFC 2046 。如:"image/png"。

::: tip 请注意 Ajv 没有实现关键字 examplecontentEncodingcontentMediaType 的验证,但保留了它们。如果您想创建一个插件来实现其中的一些关键字,应该从实例中删除这些它们。 :::

格式

Ajv 实现了由 JSON schema 规范定义的格式和一些其他格式。建议 不要 对不受信任的数据使用 format 关键字实现,因为它们使用了潜在的不安全的正则表达式。

::: tip 请注意 如果您需要使用 format 关键字来验证不受信任的数据,那么您必须评估它们对于您的验证场景的适用性和安全性。 :::

使用“format”关键字进行字符串验证,实现了下面这些格式:

  • date: 根据 RFC3339 实现的日期。
  • time: 带时区的时间。
  • data-time: 同来源的日期时间(时区是强制性的)。 datetimedate-timefull 模式下验证区间而在 fast 模式下仅用正则验证。
  • uri: full URI。
  • uri-reference: URI 引用,包括完整的和相对的 URI。
  • uri-template: 根据 RFC6570 的 URI 模板。
  • email: 邮箱地址。
  • hostname: 根据 RFC1034 的 host 名。
  • ipv4: IP 地址 v4。
  • ipv6: IP 地址 v6。
  • regex: 通过传入正则表达式构造器来验证字符串是否是一个可用的正则表达式。
  • uuid: 全局惟一标识符。根据 RFC4122
  • json-pointer: 根据 RFC6901 的 JSON 指针。
  • relative-json-pointer: 根据 该草案 的相对 JSON 指针。

::: tip 请注意 JSON Schema draft-07 同样为 URL、域名、邮箱定义了 iriiri-referenceidn-hostnameidn-email 格式。不过 Ajv 并未实现他们。如果您创建了实现它们的 Ajv 插件,请提 PR。 :::

格式验证有两种模式: fastfull 。模式会影响 datetimedate-timeuriuri-referenceemail 。请参见 配置项 文档。

unknownFormats 配置项允许在遇到未知格式时更改默认行为。在这种情况下,Ajv 要么模式编译失败(默认情况),要么忽略它(在 5.0.0 版本之前是这样的)。你还可以指定哪些格式可以忽略。

您可以找到用于格式验证的正则表达式以及 formats.js 中使用的源代码。

使用 $ref 组合 schema

您可以跨多个 schema 文件组合验证逻辑,并通过 $ref 关键字让 schema 相互引用。

示例:

var schema = {
  "$id": "http://example.com/schemas/schema.json",
  "type": "object",
  "properties": {
    "foo": { "$ref": "defs.json#/definitions/int" },
    "bar": { "$ref": "defs.json#/definitions/str" }
  }
};

var defsSchema = {
  "$id": "http://example.com/schemas/defs.json",
  "definitions": {
    "int": { "type": "integer" },
    "str": { "type": "string" }
  }
};

现在您可以将所有的 schema 传给 Ajv 实例来编译您的 schema。

var ajv = new Ajv({schemas: [schema, defsSchema]});
var validate = ajv.getSchema('http://example.com/schemas/schema.json');

也可以使用 addSchema 方法:

var ajv = new Ajv;
var validate = ajv.addSchema(defsSchema)
                  .compile(schema);

参见 配置项addSchema 方法.

请注意:

  • 使用 schema id 作为基本 URI (参见示例),将 $ref 作为 URI 引用。
  • 引用可以是递归的(也可以相互递归),以实现不同数据结构(如链表、树、图等) 的 schema。
  • 您不必将 schema 文件放到作为 schema id 的 URI 当中。这些 URI 仅用于定义 schema,根据 JSON schema 模式规范,验证器不应该期望能够从这些 URI 中下载 schema。
  • 没有使用 schema 文件在文件系统中的实际位置。
  • 您可以将 schema 的标识符作为 addSchema 方法的第二个参数或是 schema 配置项中的属性名称进行传递。该标识符可以用来代替 schema $id (或作为 schema $id 的补充)。
  • 不能将相同的 $id (或 schema 标识符) 用于多个 schema -- 这将引发异常。
  • 您可以使用 compileAsync 方法实现引用 schema 的动态解析。通过这种方式,您可以在任何系统(文件、web、数据库等) 中存储 schema 并引用它们,而无需显式地添加到 Ajv 实例中。参见 异步 schema 编译

$data 引用

通过 $data 配置项,您可以使用来自验证数据的值作为 schema 关键字的值。可以看看 这里 来了解它的原理。

$data 支持在下面的关键字当中都是支持的:const, enum, format, maximum/minimum, exclusiveMaximum / exclusiveMinimum, maxLength / minLength, maxItems / minItems, maxProperties / minProperties, formatMaximum / formatMinimum, formatExclusiveMaximum / formatExclusiveMinimum, multipleOf, pattern, required, uniqueItems.

"$data" 的值应该是指向数据的 JSON-Pointer (即使 $data 引用在被引用的子 schema 中,根始终是顶级数据对象) 或 relative JSON-Pointer (相对于数据中的当前点;如果 $data 引用在被引用的子 schema 中,那么它就不能指向这个子 schema 的根以外的数据)。

示例:

该 schema 要求 smaller 属性的值小于或等于 bigger 属性中的值:

var ajv = new Ajv({$data: true});

var schema = {
  "properties": {
    "smaller": {
      "type": "number",
      "maximum": { "$data": "1/larger" }
    },
    "larger": { "type": "number" }
  }
};

var validData = {
  smaller: 5,
  larger: 7
};

ajv.validate(schema, validData); // true

该 schema 要求属性与他们的字段名具有相同的格式:

var schema = {
  "additionalProperties": {
    "type": "string",
    "format": { "$data": "0#" }
  }
};

var validData = {
  'date-time': '1963-06-19T08:30:06.283185Z',
  email: 'joe.bloggs@example.com'
}

$data 引用会被安全地解析——即使某些属性未定义也不会抛出错误。如果 $data 解析为 undefined ,则验证成功(排除 const 关键字)。如果 $data 解析为不正确的类型(比方说, maximum 关键字的值不是"number"),验证将失败。

$merge 和 $patch 关键字

通过 ajv-merge-patch 这个包,您可以使用 $merge 关键字和 $patch 关键字,它们允许使用 JSON Merge Patch (RFC 7396)JSON Patch (RFC 6902) 来扩展 JSON Schema。

要向 Ajv 实例中添加 $mergepatch 关键字您可以这样:

require('ajv-merge-patch')(ajv);

示例:

使用 $merge

{
  "$merge": {
    "source": {
      "type": "object",
      "properties": { "p": { "type": "string" } },
      "additionalProperties": false
    },
    "with": {
      "properties": { "q": { "type": "number" } }
    }
  }
}

使用 $patch

{
  "$patch": {
    "source": {
      "type": "object",
      "properties": { "p": { "type": "string" } },
      "additionalProperties": false
    },
    "with": [
      { "op": "add", "path": "/properties/q", "value": { "type": "number" } }
    ]
  }
}

上面的 schema 等同于下面的:

{
  "type": "object",
  "properties": {
    "p": { "type": "string" },
    "q": { "type": "number" }
  },
  "additionalProperties": false
}

关键字 $merge$patch 中的 sourcewith 属性可以使用绝对或相对的 $ref 来指向之前添加到 Ajv 实例中的其他 schema 或当期 schema 的片段。

参见左边的 Ajv-merge-patch 文档获得更多信息。

自定义关键字

使用自定义关键字的好处如下:

  • 允许创建无法使用 JSON schema 表示的验证场景。
  • 简化您的 schema。
  • 有助于为 schema 引入更大一部分验证逻辑。
  • 使 schema 更具表达性、更简洁、更接近应用。
  • 实现自定义数据处理来修改数据(修改项 必须 在关键字定义中使用) 和/或在验证数据时创建副作用。

如果一个关键字只用于副作用,并且它的验证结果是预先定义的,那么在关键字定义中使用 valid: true/false 配置项来简化生成的代码(在 valid: true 的情况下没有错误处理) 和关键字函数(不需要返回任何验证结果)。

在使用自定义关键字扩展 JSON Schema 标准时,必须注意您的 schema 的可移植性和礼节性。您必须在其他平台上支持这些自定义关键字,且进行正确的文档说明,方便每个人都能理解。

您也可以使用 addKeyword 方法自定义关键字。关键字是在 ajv 实例级别上定义的----新实例没有以前定义的关键字。

Ajv 允许通过以下方式定义关键字:

  • 验证函数
  • 编译函数
  • 宏函数
  • 内联编译函数,它的作用是返回当前编译 schema 中的内联编译代码(作为字符串)。

示例,使用编译 schema 的 rangeexclusiveRange 关键字:

ajv.addKeyword('range', {
  type: 'number',
  compile: function (sch, parentSchema) {
    var min = sch[0];
    var max = sch[1];

    return parentSchema.exclusiveRange === true
            ? function (data) { return data > min && data < max; }
            : function (data) { return data >= min && data <= max; }
  }
});

var schema = { "range": [2, 4], "exclusiveRange": true };
var 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 包中定义了数个自定义关键字( typeofinstanceofrangepropertyNames ) 它们可以在您的 schema 中使用,并作为您自己的自定义关键字的起点。

参见 自定义关键字 获取更多信息。

异步 schema 编译

在异步编译期间,使用提供的函数加载远程引用。参见 compileAsync方法loadSchema配置项

示例:

var ajv = new Ajv({ loadSchema: loadSchema });

ajv.compileAsync(schema).then(function (validate) {
  var valid = validate(data);
  // ...
});

function loadSchema(uri) {
  return request.json(uri).then(function (res) {
    if (res.statusCode >= 400)
      throw new Error('Loading error: ' + res.statusCode);
    return res.body;
  });
}

::: warning 请注意 配置项 missingRefs 不应该在异步编译时设置为 "ignore""fail" 。 :::

异步验证

Node.js 交互式编程环境(REPL) 的 示例

您可以通过访问数据库或其他服务来定义执行异步验证的自定义格式和关键字。您应该在关键字或格式定义中添加 async: true (参见 addFormataddKeyword定义自定义关键字 )

如果您的 schema 使用了异步格式/关键字,或者应用了一些包含这些关键字的 schema,那么它应该带有 "$async": true 关键字,以便 Ajv 能够正确编译它。如果在没有 $async 关键字的 schema 中使用异步格式/关键字或对异步 schema 的引用,那么 Ajv 将在 schema 编译期间抛出异常。

::: tip 请注意 从当前 schema 或其他 schema 引用的所有异步子 schema 也应该具有 "$async":true 关键字,否则模式编译将失败。 :::

异步自定义格式/关键字的验证函数应该返回一个结果为 truefalse 的 Promise (或者如果希望从关键字函数返回自定义错误,则使用 reject 返回 new Ajv.ValidationError(errors) )。

Ajv 将异步 schema 编译为 async 函数,它们可以使用 nodent 进行转换。Node.js 7+ 和所有现代浏览器都支持 async 函数。您还可以通过 processCode 配置项提供作为函数的其他转换器。参见 配置项

编译后的验证函数具有 $async: true 属性(如果模式是异步的),因此如果同时使用同步模式和异步模式,您可以将它们区分开来。

验证结果是一个返回验证数据(resolve) 或带有 Ajv.ValidationError (reject) 的 Promise。

示例:

var ajv = new Ajv;
// require('ajv-async')(ajv);

ajv.addKeyword('idExists', {
  async: true,
  type: 'number',
  validate: checkIdExists
});


function checkIdExists(schema, data) {
  return knex(schema.table)
  .select('id')
  .where('id', data)
  .then(function (rows) {
    return !!rows.length; // true if record is found
  });
}

var schema = {
  "$async": true,
  "properties": {
    "userId": {
      "type": "integer",
      "idExists": { "table": "users" }
    },
    "postId": {
      "type": "integer",
      "idExists": { "table": "posts" }
    }
  }
};

var validate = ajv.compile(schema);

validate({ userId: 1, postId: 19 })
.then(function (data) {
  console.log('Data is valid', data); // { userId: 1, postId: 19 }
})
.catch(function (err) {
  if (!(err instanceof Ajv.ValidationError)) throw err;
  // data is invalid
  console.log('Validation errors:', err.errors);
});

使用带有异步验证函数的转换器

ajv-async 使用 nodent 来转换异步函数。要使用另一个转换器,你应该单独安装它(或在浏览器中加载它的包)。

使用 nodent:

var ajv = new Ajv;
require('ajv-async')(ajv);
// 在浏览器环境,如果您想单独加载 ajv-async 的包,您可以使用:
// window.ajvAsync(ajv);
var validate = ajv.compile(schema); // 转换 es7 async function
validate(data).then(successFunc).catch(errorFunc);

使用其他转换器:

var ajv = new Ajv({ processCode: transpileFunc });
var validate = ajv.compile(schema); // 转换 es7 async function
validate(data).then(successFunc).catch(errorFunc);

安全注意事项

如果使用得当,JSON Schema 可以替代数据清理,但并不会取代其他的 API 安全注意事项。它引入了其它需要考虑的安全方面的事项。

安全隐患汇报

若要报告安全漏洞,请使用 Tidelift 安全隐患汇报 。Tidelift 将协调修复和披露安全隐患。请不要使用 GitHub 报告安全漏洞。

不可信的 schema

Ajv 将 JSON schema 视为受信任的代码。该安全模型基于最常见的用例,即 schema 是静态的并与应用程序绑定在一起。

如果您的 schema 是从不可信的来源获得的(或是从不可信数据生成的),那么下面几种情况就是您要竭力避免的:

  • 编译 schema 可能导致堆栈溢出(如果太深的话)。
  • 编译 schema 可能太慢了。
  • 验证某些数据较慢。

虽然很难预测所有的场景,但至少它可以帮助限制不可信 schema 的大小(例如限制 JSON 字符串长度) 和 schema 对象的最大深度(相对于较小的 JSON 字符串,这个深度可能很高)。您还可以将较慢的正则表达式放到 patternpatternProperties 关键字中。

无论您采取何种措施,使用不受信任的模式都会增加安全风险。

JavaScript 对象中的循环引用

Ajv 不支持在对象中具有循环引用的 schema 和验证数据。参见 这里

尝试编译这样的 schema 或验证这样的数据会导致堆栈溢出(或者异步验证不会完成)。根据所使用的解析器的不同,不受信任的数据可能导致循环引用。

受信任 schema 的安全风险

JSON schema 中的一些关键字可能导致对某些数据的验证非常缓慢。这些数字包括(但可能不限于):

  • patternformat 匹配大量字符串 ———— 在某些情况下 maxLength 可以帮我我们缓解它,但某些正则表达式可能导致验证时间呈指数级增长,即使是相对较短的字符串(参见下面的 ReDoS 攻击)。
  • patternProperties 匹配大量属性名称 ———— 使用 propertyNames 来缓解,但是一些正则表达式也可能会有指数级的计算时间。
  • 用于大型非表里数组的 uniqueItems ———— 使用 maxItems 来缓解。

::: warning 请注意 只有在生产环境代码中不使用 allErrors:true 时,上面防止缓慢验证的建议才起效(使用它将在验证错误之后继续验证)。 :::

您可以根据 元 schema 来验证您的 JSON schema 以检查是否遵循了以下协议:

const isSchemaSecure = ajv.compile(require('ajv/lib/refs/json-schema-secure.json'));

const schema1 = {format: 'email'};
isSchemaSecure(schema1); // false

const schema2 = {format: 'email', maxLength: MAX_LENGTH};
isSchemaSecure(schema2); // true

::: warning 谨记 遵循所有这些建议并不能保证对不可信数据的验证是安全的 ———— 凡事总有意外嘛。 :::

正则 Dos 攻击(ReDos Attack)

即使字符串相对较短,某些正则表达式也可能导致计算时间呈指数级成长。

请评估您在模式中使用的正则表达式对这种攻击的抵抗力 —— 参见 安全正则

::: tip 请注意 Ajv 使用 正则表达式 实现了一些格式,它们容易遭到 ReDoS 攻击,所以如果你使用 Ajv 验证来自不可信来源的数据,强烈建议考虑以下几点:

  • 评估 Ajv 中"格式"的实现。
  • 使用 format: 'fast' 配置项简化了一些正则表达式(尽管这也不能保证它们是安全的)。
  • 将 Ajv 提供的格式实现替换成您自己的 format 关键字实现,这些实现使用不同的正则表达式或另一种格式验证方法。参见 addFormat 方法。
  • 禁用格式验证,使用 format: false 忽略 format 关键字。

无论您选择哪种措施,请先假定 Ajv 提供的所有格式都不安全,并自行评估它是否适合您的验证场景。 :::

过滤数据

利用 removeAdditional 配置项您可以在验证期间过滤数据。

它会修改原始数据。

示例:

var ajv = new Ajv({ removeAdditional: true });
var schema = {
  "additionalProperties": false,
  "properties": {
    "foo": { "type": "number" },
    "bar": {
      "additionalProperties": { "type": "number" },
      "properties": {
        "baz": { "type": "string" }
      }
    }
  }
}

var data = {
  "foo": 0,
  "additional1": 1, // 将会被移除; `additionalProperties` == false
  "bar": {
    "baz": "abc",
    "additional2": 2 // 不会被移除; `additionalProperties` != false
  },
}

var validate = ajv.compile(schema);

console.log(validate(data)); // true
console.log(data); // { "foo": 0, "bar": { "baz": "abc", "additional2": 2 }

如果上面示例中的 removeAdditional 配置项是 "all" ,那么 additional1additional2 属性都将被删除。

如果配置项是 "failing" 那么 additional1 就已经被移除,无论其值为多少。 additional2 则只有当它的值在内部 additionalProperties 中的 schema 中失败时会被移除(因此在上面的示例中,它会保留下来,因为它传递了 schema,但任何非数字将被删除)。

::: warning 请注意 如果你使用的 removeAdditional 配置项内含有带有 additionalPropertiesanyOf / oneOf 关键字,你的验证可能会失败,例如:

{
  "type": "object",
  "oneOf": [
    {
      "properties": {
        "foo": { "type": "string" }
      },
      "required": [ "foo" ],
      "additionalProperties": false
    },
    {
      "properties": {
        "bar": { "type": "integer" }
      },
      "required": [ "bar" ],
      "additionalProperties": false
    }
  ]
}

:::

上述 schema 的旨在允许字符串属性“foo”或整数属性“bar”的对象,但不允许同时具有这两个属性或任何其他属性的对象。

当配置了 removeAdditional: true 时,对象 {" foo": "abc"} 会通过验证,但 {"bar": 1} 会失败。发生这种情况的原因是,当验证 oneOf 第一个子级 schema 时,属性 bar 被删除了,因为根据标准,它是一个附加属性(因为它并未包含在相同 schema 的 properties 关键字中)。

虽然这种情况是意料之外的,但它是正确的。开发者若想达成期望的行为(两个对象中都是合法属性,但附加属性被删除了),需要对 schema 按照以下方式重构:

{
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "type": "integer" }
  },
  "additionalProperties": false,
  "oneOf": [
    { "required": [ "foo" ] },
    { "required": [ "bar" ] }
  ]
}

上面的 schema 更有效,它编译成的函数更快。

配置默认值

通过 useDefaults 配置项,Ajv 将把 pripertiesitems 的 schema (当它是 schema 数组时) 中的 default 关键字的值配置给丢失的属性和项。

当配置项为 "empty" 时,属性和项的值为 null"" (空字符串) 会被认为丢失并设置为默认值。

该配置项会修改原始数据。

::: tip 请注意 默认值作为文本被插入到生成的验证代码中,因此插入到数据中的值将是 schema 中默认值的深拷贝。 :::

示例 1 ( properties 中的 default ):

var ajv = new Ajv({ useDefaults: true });
var schema = {
  "type": "object",
  "properties": {
    "foo": { "type": "number" },
    "bar": { "type": "string", "default": "baz" }
  },
  "required": [ "foo", "bar" ]
};

var data = { "foo": 1 };

var validate = ajv.compile(schema);

console.log(validate(data)); // true
console.log(data); // { "foo": 1, "bar": "baz" }

示例 2 ( items 中的 default ):

var schema = {
  "type": "array",
  "items": [
    { "type": "number" },
    { "type": "string", "default": "foo" }
  ]
}

var data = [ 1 ];

var validate = ajv.compile(schema);

console.log(validate(data)); // true
console.log(data); // [ 1, "foo" ]

其他情况 default 关键字会被忽略:

  • 不在 propertiesitems 的子级 schema 中。
  • anyOfoneOfnot 中的 schema 中。
  • switch 关键字的 if 子级 schema 中。
  • 在由自定义宏关键字生成的 schema 中。

strictDefaults 配置项定制了 Ajv 的行为,补强了 Ajv 忽略掉的默认值情况(设置为 true 会引发错误, "log" 则会输出警告)。

强制数据类型转换

在验证用户输入时,所有数据属性通常都是字符串。 coerceTypes 配置项允许您将数据类型强制转换为 schema type 关键字中指定的类型,以便通过验证并在之后使用正确类型的数据。

该配置项会修改原始数据。

::: warning 请注意 如果您将值类型传递给验证函数,它将被强制规定类型并且通过验证,但是您传递的变量的值将不会被更新,因为值类型是按值传递的。 :::

示例 1:

var ajv = new Ajv({ coerceTypes: true });
var schema = {
  "type": "object",
  "properties": {
    "foo": { "type": "number" },
    "bar": { "type": "boolean" }
  },
  "required": [ "foo", "bar" ]
};

var data = { "foo": "1", "bar": "false" };

var validate = ajv.compile(schema);

console.log(validate(data)); // true
console.log(data); // { "foo": 1, "bar": false }

示例 2(强制数组):

var ajv = new Ajv({ coerceTypes: 'array' });
var schema = {
  "properties": {
    "foo": { "type": "array", "items": { "type": "number" } },
    "bar": { "type": "boolean" }
  }
};

var data = { "foo": "1", "bar": ["false"] };

var validate = ajv.compile(schema);

console.log(validate(data)); // true
console.log(data); // { "foo": [1], "bar": false }

从示例中可以看到,强制规则与 JavaScript 是不同的,它可以按期望验证用户输入,并让过程可逆(从而正确验证在“anyOf”和其他复合关键字的子级 schema 中定义不同类型的情况)。

参见 强制类型转换 文档了解更多细节。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文