小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
前端小知识 | JSONSchema
JSON Schema
-
定义 JSON 数据和规范
-
校验数据工具 Ajv.js
如何定义 Schema
yarn add ajv
// schema-tests/test1.js
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Ajv = require('ajv') //
const ajv = new Ajv()
// 校验规则
const schema = {
type: 'string', // 必须是字符串
minLength: 10, // 最小 10 位
}
const validate = ajv.compile(schema)
const valid = validate('damowang')
if (!valid) console.log(validate.errors)
$ node ./schema-tests/test1.js
[
{
instancePath: '',
schemaPath: '#/minLength',
keyword: 'minLength',
params: { limit: 10 },
message: 'must NOT have fewer than 10 characters'
}
]
定义对象校验规则
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Ajv = require('ajv') //
const ajv = new Ajv()
const schema = {
type: 'object',
properties: {
name: {
type: 'string',
},
age: {
type: 'number',
},
pets: {
type: 'array',
items: {
type: 'string',
},
},
isWorker: {
type: 'boolean',
},
},
required: ['name', 'age'], //哪些属性是必须输入的
}
const validate = ajv.compile(schema)
const valid = validate({
name: 'damowang',
age: 10,
pets: [],
isWorker: false,
})
if (!valid) console.log(validate, validate.errors)
自定义 Format
Format 只针对于 string 和 number
.addFormat(String , String|RegExp|Function|Object format) => Ajv
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Ajv = require('ajv') //
const ajv = new Ajv()
// 自定义 Format
ajv.addFormat('test', (data) => {
console.log(data, '--------')
return data === 'hahaha'
})
const schema = {
type: 'object',
properties: {
name: {
type: 'string',
format: 'test',
},
age: {
type: 'number',
},
pets: {
type: 'array',
items: {
type: 'string',
},
},
isWorker: {
type: 'boolean',
},
},
required: ['name', 'age'], //哪些属性是必须输入的
}
const validate = ajv.compile(schema)
const valid = validate({
name: 'damowang',
age: 10,
pets: [],
isWorker: false,
})
if (!valid) console.log(validate, validate.errors)
如何在 AJV 中自定义关键字
方式 1 validate
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Ajv = require('ajv') //
const ajv = new Ajv()
ajv.addFormat('test', (data) => {
console.log(data, '--------')
return data === 'hahaha'
})
ajv.addKeyword('testKeyword', {
validate(schema, data) {
console.log(schema, data)
console.log(schema.length)
if (schema === true) return true
else return schema.length === 6
},
})
const schema = {
type: 'object',
properties: {
name: {
type: 'string',
// format: 'test',
testKeyword: 'hahaha',
},
age: {
type: 'number',
},
pets: {
type: 'array',
items: {
type: 'string',
},
},
isWorker: {
type: 'boolean',
},
},
required: ['name', 'age'], //哪些属性是必须输入的
}
const validate = ajv.compile(schema)
const valid = validate({
name: 'hahaha',
age: 10,
pets: [],
isWorker: false,
})
if (!valid) console.log(validate, validate.errors)
方式 2 compile
ajv.addKeyword('testKeyword', {
compile(sch, parentSchema) {
console.log(sch, parentSchema)
return () => true
},
})
方式 3 metaSchema
ajv.addKeyword('testKeyword', {
compile(sch, parentSchema) {
console.log(sch, parentSchema)
return () => true
},
metaSchema: {
type: 'string',
},
})
方式 4 macro
ajv.addKeyword('testKeyword', {
macro() {
return {
minLength: 10,
}
},
})
如何在 AJV 中如何转换错误信息语言
安装 ajv-i18n
yarn add ajv-i18n
配置代码
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Ajv = require('ajv') //
const ajv = new Ajv()
// eslint-disable-next-line @typescript-eslint/no-var-requires
const localize = require('ajv-i18n')
ajv.addFormat('test', (data) => {
console.log(data, '--------')
return data === 'hahaha'
})
const schema = {
type: 'object',
properties: {
name: {
type: 'number',
},
age: {
type: 'number',
},
pets: {
type: 'array',
items: {
type: 'string',
},
},
isWorker: {
type: 'boolean',
},
},
required: ['name', 'age'], //哪些属性是必须输入的
}
const validate = ajv.compile(schema)
const valid = validate({
name: 'hahahahaaha',
age: 10,
pets: [],
isWorker: false,
})
if (!valid) {
// 返回中文错误信息
localize.zh(validate.errors)
console.log(validate, validate.errors)
}
$ node ./schema-tests/test1.js
[
...
{
instancePath: '/name',
schemaPath: '#/properties/name/type',
keyword: 'type',
params: { type: 'number' },
message: '应当是 number 类型'
}
]
如何在 JSONSchema 中定制校验错误信息
安装依赖
yarn add ajv-errors
代码示例
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Ajv = require('ajv') //
const ajv = new Ajv({ allErrors: true, jsonPointers: true })
// eslint-disable-next-line @typescript-eslint/no-var-requires
require('ajv-errors')(ajv)
const schema = {
type: 'object',
properties: {
name: {
type: 'string',
// test: false,
errorMessage: {
type: '必须是字符串',
minLength: '长度不能小于 10',
},
minLength: 11,
},
age: {
type: 'number',
},
pets: {
type: 'array',
items: {
type: 'string',
},
},
isWorker: {
type: 'boolean',
},
},
required: ['name', 'age'], //哪些属性是必须输入的
}
const validate = ajv.compile(schema)
const valid = validate({
name: 'h',
age: 10,
pets: [],
isWorker: false,
})
if (!valid) {
console.log(validate.errors)
}