Dear,大家好,我是“前端小鑫同学”,😇长期从事前端开发,安卓开发,热衷技术,在编程路上越走越远~
JSON Schema:
JSON Schema是一份用来注释和验证JSON文档开源草案,通过JSON Schema可以描述现有的数据格式,可以完成数据的自动化测试,可以有效保障数据提交的质量。
Ajv介绍及使用:
在JavaScript领域,Ajv 提供了完整的符合 JSON Schema 规范的数据校验。Ajv 的赞助商有moz://a、Microsoft等,使用Ajv的开源项目也非常多,如:ESLint、webpack等,并且在NodeJs、浏览器、桌面应用程序、微信小程序等平台均有应用。

上手使用:
使用步骤说明:
- 安装、导入、实例化:
| |
| const Ajv = require('ajv'); |
| const ajv = new Ajv(); |
- 定义schema;
- 执行compile生成validate函数;
- 执行validate函数检查数据。
schema定义说明:
- type设置为object表示目标JSON文档是一个对象;
- properties设置这个对象的属性包括foo、bar并分别指明其类型;
- required通过列表的形式限制foo为必填项;
- additionalProperties设置为false表示仅能包已声明的属性**。**
常见类型的定义:
- 定义对象类型:
| const schema = { |
| type: 'object', |
| properties: { |
| attribute1, |
| attribute2, |
| ... |
| }, |
| required: ['attribute1'], |
| additionalProperties: false, |
| } |
- 定义字符串类型:
| const schema = { |
| type: 'string', |
| minLength: 10, |
| } |
- 定义数字类型:
| const schema = { type: 'number' } |
- 定义布尔类型:
| const schema = { type: 'boolean' } |
- 定义数组/类数组类型:
| const schema = { |
| type: 'array', |
| items: { |
| type: 'string' |
| } |
| } |
| |
| const schema = { |
| type: 'array', |
| items: [ |
| { |
| type: 'number' |
| },{ |
| type: 'string' |
| } |
| ] |
| } |
案例代码:
运行下面的代码会同时得到三条违反规则的提示:
- fn1:must NOT have additional properties,不需要额外的属性出现。
- /foo:must be integer,仅支持整数。
- /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, |
| }; |
| |
| |
| 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工作。
- 安装、导入、初始化:
| |
| const addFormats = require('ajv-formats'); |
| |
| |
| addFormats(ajv); |
- 内置的format关键字有:date、time、date-time、uri、url、email等。
- format仅作用于类型为string或number的属性。
自定义Format:
- 使用addFormat增加一个通过正则验证完成的Format:
| ajv.addFormat("identifier", /^a-z\$_[a-zA-Z$_0-9]*$/) |
- 仅作用在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', |
| }, |
| }, |
| }; |
| |
| |
| 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" }, |
| |
| 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) { |
| |
| 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, |
| }); |
多语言支持:
使用步骤说明:
- 安装、导入、初始化:
| |
| const 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); |
| } |

自定义错误信息:
使用步骤说明:
- 安装、导入、配置:
| |
| |
| |
| require("ajv-errors")(ajv); |
| |
| |
| errorMessage: { |
| type: "必须是字符串", |
| minLength: "输入的用户名太短了", |
| } |
- 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); |
| } |

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)