写点什么

【Ajv】JSON Schema Validator

作者:小鑫同学
  • 2022-10-13
    北京
  • 本文字数:3754 字

    阅读完需:约 12 分钟

【Ajv】JSON Schema Validator

大家好,我是小鑫同学。一位从事过 Android 开发混合开发,现在长期从事前端开发的编程爱好者,我觉得在编程之路上最重要的是知识的分享,所谓三人行必有我师。所以我开始在社区持续输出我所了解到、学习到、工作中遇到的各种编程知识,欢迎有想法、有同感的伙伴加我fe-xiaoxin微信交流~

JSON Schema:

JSON Schema 是一份用来注释和验证 JSON 文档开源草案,通过 JSON Schema 可以描述现有的数据格式,可以完成数据的自动化测试,可以有效保障数据提交的质量。

Ajv 介绍及使用:

JavaScript 领域,Ajv 提供了完整的符合 JSON Schema 规范的数据校验。Ajv 的赞助商有 moz://aMicrosoft 等,使用 Ajv 的开源项目也非常多,如:ESLintwebpack 等,并且在 NodeJs浏览器桌面应用程序微信小程序等平台均有应用。


上手使用:

使用步骤说明:

  1. 安装、导入、实例化:


// npm i ajvconst Ajv = require('ajv');const ajv = new Ajv();
复制代码


  1. 定义 schema;

  2. 执行 compile 生成 validate 函数;

  3. 执行 validate 函数检查数据。

schema 定义说明:

  1. type 设置为 object 表示目标 JSON 文档是一个对象;

  2. properties 设置这个对象的属性包括 foo、bar 并分别指明其类型;

  3. required 通过列表的形式限制 foo 为必填项;

  4. additionalProperties 设置为 false 表示仅能包已声明的属性**。**

常见类型的定义:

  1. 定义对象类型:


const schema = {  type: 'object',  properties: {    attribute1,    attribute2,    ...  },  required: ['attribute1'], // 必填属性  additionalProperties: false, // 禁止多余属性}
复制代码


  1. 定义字符串类型:


const schema = {  type: 'string',  minLength: 10, // 最小长度需满足10}
复制代码


  1. 定义数字类型:


const schema = { type: 'number' }
复制代码


  1. 定义布尔类型:


const schema = { type: 'boolean' }
复制代码


  1. 定义数组/类数组类型:


const schema = {  type: 'array',  items: {    type: 'string' // 定义数组的每一项均为字符串类型  }}// andconst schema = {  type: 'array',  items: [  // 定义数据包含两个元素,元素1位数字类型,元素2为字符串类型    {      type: 'number'    },{      type: 'string'    }  ]}
复制代码

案例代码:

运行下面的代码会同时得到三条违反规则的提示:


  1. fn1:must NOT have additional properties,不需要额外的属性出现。

  2. /foo:must be integer,仅支持整数。

  3. /bar:must be string,仅支持字符串。


const Ajv = require('ajv');const ajv = new Ajv({ allErrors: true });
const schema = { type: 'object', properties: { foo: { type: 'integer', }, bar: { type: 'string', }, }, required: ['foo'], additionalProperties: false,};
// 执行compile后validate可以多次使用const validate = ajv.compile(schema);
const data = { foo: 'foo', bar: 200, fn1: 'fn1',};
// 执行数据校验const valid = validate(data);if (!valid) { console.log(validate.errors);}
复制代码

Format 关键字:

使用步骤说明:

从 ajv7 开始由 ajv-formats 提供属性的 format 工作。


  1. 安装、导入、初始化:


// npm i ajv-formatsconst addFormats = require('ajv-formats');
// ajv 实例化后添加addFormats(ajv);
复制代码


  1. 内置的 format 关键字有:date、time、date-time、uri、url、email 等。

  2. format 仅作用于类型为 string 或 number 的属性。

自定义 Format:

  1. 使用 addFormat 增加一个通过正则验证完成的 Format:


ajv.addFormat("identifier", /^a-z\$_[a-zA-Z$_0-9]*$/)
复制代码


  1. 仅作用在 number 类型上的 Format:


ajv.addFormat("byte", {  type: "number",  validate: (x) => x >= 0 && x <= 255 && x % 1 == 0,})
复制代码

案例代码:

const Ajv = require('ajv');const addFormats = require('ajv-formats');const ajv = new Ajv({ allErrors: true });addFormats(ajv);
const schema = { type: 'object', properties: { email: { type: 'string', format: 'email', }, },};
// 执行compile后validate可以多次使用const validate = ajv.compile(schema);
const data = { email: '1825203636@qq.com',};
// 执行数据校验const valid = validate(data);if (!valid) { console.log(validate.errors);}
复制代码

自定义关键字:

自定义关键字可以弥补预定义字段无法完成的验证场景,简化程序结构。 实现 range 关键字:


const schema = {  type: "object",  properties: {    username: { type: "string" },    password: { type: "string" },    age: { type: "number" },    // 验证邮箱的长度在 5~25 个字符之间    email: { type: "string", format: "email", range: [5, 25] },  },  required: ["username", "password"],  additionalProperties: false,};
复制代码

用“validate”函数定义关键字:

通过 addKeyword 函数新增一个使用 validate 定义的关键字校验,满足在执行ajv.validate时邮箱的字段长度符合一定的区间。


ajv.addKeyword({  keyword: "range",  validate: (schema, data) => {    if (typeof schema == "object" && schema !== null && data) {      const minLength = schema[0];      const maxLength = schema[1];      if (data.length >= minLength && data.length <= maxLength) {        return true;      }    }    return false;  },  errors: false,});
复制代码

用"compile"函数定义关键字:

ajv.compile阶段会对关键字的类型进行校验,保证关键字的正确使用。


ajv.addKeyword({  keyword: "range",  compile([minLength, maxLength], parentSchema) {    // parentSchema:读取 schema 中更多的信息来做判断    return (data) => {      if (data.length >= minLength && data.length <= maxLength) {        return true;      }      return false;    };  },  // 规范自定义关键字的类型  metaSchema: {    type: "array",    items: [{ type: "number" }, { type: "number" }],    minItems: 2,    maxItems: 2,    additionalItems: false,  },  errors: false,});
复制代码

用“宏”函数定义关键字:

通过定义 macro 类型关键字可以很方便的通过一个关键字来为 schema 定义批量增加数据校验。


ajv.addKeyword({  keyword: "range",  macro: ([minLength, maxLength], parentSchema) => {    return { minLength, maxLength };  },  errors: false,});
复制代码

多语言支持:

使用步骤说明:

  1. 安装、导入、初始化:


// npm i ajv-i18nconst localize = require("ajv-i18n");
// 校验未通过后对错误内容进行转换处理localize.zh(validate.errors);
复制代码

案例代码:

const Ajv = require("ajv");const addFormats = require("ajv-formats");const localize = require("ajv-i18n");const ajv = new Ajv();addFormats(ajv);
ajv.addKeyword({ keyword: "range", macro: ([minLength, maxLength], parentSchema) => { return { minLength, maxLength }; }, errors: false,});
const schema = { type: "object", properties: { username: { type: "string" }, password: { type: "string" }, age: { type: "number" }, email: { type: "string", format: "email", range: [5, 15] }, }, required: ["username", "password"], additionalProperties: false,};
const data = { username: "xiaoxin", password: "xiaoxin", email: "1825203636@qq.com",};
const validate = ajv.compile(schema);const valid = validate(data);
if (!valid) { localize.zh(validate.errors); console.log(validate.errors);}
复制代码


自定义错误信息:

使用步骤说明:

  1. 安装、导入、配置:


// npm i ajv-errors
// ajv实例化后执行require("ajv-errors")(ajv);
// 配置字段的新属性errorMessage,针对类型和其他关键字做不同的错误提示:errorMessage: { type: "必须是字符串", minLength: "输入的用户名太短了",}
复制代码


  1. i18 库存与 ajv-errors 似乎需要特殊处理;

案例代码:

const Ajv = require("ajv");const ajv = new Ajv({ allErrors: true });require("ajv-errors")(ajv);
ajv.addKeyword({ keyword: "range", macro: ([minLength, maxLength], parentSchema) => { return { minLength, maxLength }; }, errors: false,});
const schema = { type: "object", properties: { username: { type: "string", minLength: 10, errorMessage: { type: "必须是字符串", minLength: "输入的用户名太短了", }, }, password: { type: "string" }, age: { type: "number" }, email: { type: "string", range: [5, 25] }, }, required: ["username", "password"], additionalProperties: false,};
const data = { username: "xiaoxin", password: "xiaoxin", email: "1825203636@qq.com",};
const validate = ajv.compile(schema);const valid = validate(data);
if (!valid) { console.log(validate.errors);}
复制代码



发布于: 刚刚阅读数: 3
用户头像

小鑫同学

关注

⚡InfoQ签约作者 2018-12-10 加入

还未添加个人简介

评论

发布
暂无评论
【Ajv】JSON Schema Validator_前端_小鑫同学_InfoQ写作社区