ajv-merge-patch

方便 Ajv 扩展 JSON Schema的$merge关键字和$patch关键字。

英文源文档

解决的问题

允许使用JSON Merge Patch (RFC 7396)JSON Patch (RFC 6902)中的模式补丁来扩展 JSON Schema 的$merge$patch关键字。

如果您想要向递归 schema (例如元 schema)中添加额外的属性,那么 schema 的扩展就是是必不可少的。考虑一下这个例子:

原本的 schema:

{
  "id": "mySchema.json#",
  "type": "object",
  "properties": {
    "foo": { "type": "string" },
    "bar": { "$ref": "#" }
  },
  "additionalProperties": false
}
1
2
3
4
5
6
7
8
9

验证数据:{ foo: 'a' }{ foo: 'a', bar: { foo: 'b' } }等。

如果您想要定义更多属性的 schema,那么在不使用$merge$patch关键字的情况下,唯一的方法就是复制粘贴并编辑原始的 schema。

使用$merge关键字您可以这样创建扩展后的schema

{
  "id": "mySchemaExtended.json#",
  "$merge": {
    "source": { "$ref": "mySchema.json#" },
    "with": {
      "properties": {
        "baz": { "type": "number" }
      }
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11

验证数据:{ foo: 'a', baz: 1 }{ foo: 'a', baz: 1, bar: { foo: 'b', baz: 2 } }等。

$merge是使用json-merge-patch实现的自定义宏关键字

若使用$patch关键字则是这样扩展:

{
  "id": "mySchemaExtended.json#",
  "$patch": {
    "source": { "$ref": "mySchema.json#" },
    "with": [
      {
        "op": "add",
        "path": "/properties/baz",
        "value": { "type": "number" }
      }
    ]
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

$patch是使用fast-json-patch实现的自定义宏关键字

在大多数情况下,$merge格式更容易理解和维护。$patch可以用于$merge无法表达的扩展和更改,例如添加数组值

关键字中的with属性还可以是对某个 schema 的部分引用,在这种情况下,将使用解析的值,而不是使用带有$ref属性的实际对象。

请注意:

  1. 如果sourceschema 或with关键字的patch使用了$ref,它们将不会考虑福对象定义的内部$ref的解析作用域——它们将会作为单独的对象来使用。
  2. sourceschema或with中的$ref都考虑了当前$ref的解析作用域(从 2.0.0 版本开始)。

参考资料:

  1. V5 proposal;
  2. $merge and $patch tests;
  3. JSON-Schema-Org 的讨论

在 Ajv 中使用

这些关键字需要兼容的 Ajv 版本 >= 5.1.0-beta.0。

将这些关键字加入到 Ajv 实例:

var Ajv = require('ajv');
var ajv = new Ajv();
require('ajv-merge-patch')(ajv);
1
2
3

在浏览器中使用

您也可以使用 browserify 添加这些关键字。

// merge
require('ajv-merge-patch/keywords/merge')(ajv);
// patch
require('ajv-merge-patch/keywords/patch')(ajv);
1
2
3
4