【vue3学习系列】json-schema的学习

文章目录

概念

json-schema我觉得把它类比成json的增强interface就比较好理解。

引用:Json Schema定义了一套词汇和规则,这套词汇和规则用来定义Json元数据,且元数据也是通过Json数据形式表达的。Json元数据定义了Json数据需要满足的规范,规范包括成员、结构、类型、约束等。

安装

此次我们使用一个比较流行的基于json-schema标准实现的库,AJV。还是在vue3的项目上:

cnpm i ajv -S

使用

可以新建个src同级文件夹,里面放json-schema的测试文件,比如json-schema/test.js:

// 官方案例
const Ajv = require("ajv");
const ajv = new Ajv(); // options can be passed, e.g. {allErrors: true}

const schema = {
  type: "object", // 类型
  properties: {
    // 对象上的属性(特征)
    foo: { type: "number" },
    bar: { type: "string" },
  },
  required: ["foo"], // 必输入项
  additionalProperties: false,
};

const validate = ajv.compile(schema);

const data = {
  foo: 1,
  bar: 1, // 故意输错
};

const valid = validate(data);
if (!valid) console.log(validate.errors);

cd到文件夹下直接node test.js跑起来,会打印出:

{
  instancePath: '/bar',
  schemaPath: '#/properties/bar/type',
  keyword: 'type', // 类型错误
  params: { type: 'string' },
  message: 'must be string' // 错误信息
}

可能在写的过程中,eslint会报错,需要在src同级下创建个.eslintignore文件用来忽略schema-tests文件下的检测:

schema-tests

format

感觉就是ajv内置的一些字符串和数字的校验规则。

对应官方文档:https://ajv.js.org/guide/formats.html#string-formats

其中的addFormat可以自定义format规则。

自定义关键字

类似type、properties等就是关键字。如何自定义关键字的内部逻辑有多种方案。

validate方案

const Ajv = require("ajv");
const ajv = new Ajv();

const schema = {
  type: "object",
  properties: {
    input: { type: "string", fnCheck: true },
  },
};

ajv.addKeyword("fnCheck", {
  validate(schema, data) { // addKeyword内部逻辑的现实有多种,先看看validate方案
    // schema为新增fnCheck关键字的值,为true,data为添加这个关键字的对象的值,input为'1234'
    if (data === "123") return true;
    else return false;
  },
});
const validate = ajv.compile(schema);

const data = {
  input: "1234",
};

const valid = validate(data);
if (!valid) console.log(validate.errors);

此时运行就会提示没通过fnCheck的校验:

{
   instancePath: '/input',
   schemaPath: '#/properties/input/fnCheck',
   keyword: 'fnCheck',
   params: {},
   message: 'must pass "fnCheck" keyword validation'
}

compile方案:

const Ajv = require("ajv");
const ajv = new Ajv();

const schema = {
  type: "object",
  properties: {
    input: { type: "string", fnCheck: true },
  },
};

ajv.addKeyword("fnCheck", {
  compile(sch, parentSchema) {
    // sch 为新增key的值,例如fnCheck的true。parentSchema取的是新增key所在的父级内容,也就是{ type: "string", fnCheck: true }
    return () => true; // 注意的是要返回一个函数,如果你想返回值需要通过返回的函数再返回出去
  },
  metaSchema: {
    type: "boolean", // 定义新增key值的类型
  },
});
const validate = ajv.compile(schema);

const data = {
  input: "1234",
};

const valid = validate(data);
if (!valid) console.log(validate.errors);

macro方案:

const Ajv = require("ajv");
const ajv = new Ajv();

const schema = {
  type: "object",
  properties: {
    input: { type: "string", fnCheck: true, minLength: 10, maxLength: 20 },
  },
};

ajv.addKeyword("fnCheck", {
  macro() {
    // 会把返回的内容全部加到新增key的下面
    return {
      minLength: 10,
      maxLength: 20,
    };
  },
});
const validate = ajv.compile(schema);

const data = {
  input: "1234",
};

const valid = validate(data);
if (!valid) console.log(validate.errors);

剩下一个inline方案,虽然性能上是最优的,但是可读性很差,就不记录了。

上一篇:mongodb安装配置


下一篇:常用品牌交换机端口镜像(Port Mirroring)配置