如何使用 Ajv 编译 JSON 架构的子集?

How can I compile a subset of a JSON Schema with Ajv?

我必须遵循 JSON 架构:

{
  "type": "object",
  "required": [
    "type",
    "title"
  ],
  "properties": {
    "type": {
      "enum": [
        "journal",
        "book",
        "generic"
      ]
    },
    "title": {
      "type": "string",
      "minLength": 1,
      "maxLength": 500
    }
  }
}

根据该架构,以下 object 有效:

{type: 'journal', title: 'foo'}

而这个不是:

{type: 'qux', title: ''}

有没有一种方法可以重用该架构的子集,以便我可以单独验证类型和标题?

例如(在伪代码中)

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

ajv.addSchema(/* see schema above */);

const validate_document = ajv.compile(/* see schema above */);
const validate_type = ajv.compile(/* reuse corresponding subset */);
const validate_title = ajv.compile(/* reuse corresponding subset */);

validate_document({type: 'qux', title: ''}); // false
validate_type('qux'); // false
validate_title(''); // false

我选择了这个解决方案,它允许我保留模式 "integrity"(我不需要将它分成更小的部分,这样它仍然易于阅读和理解)。 我需要做的就是在相关模式上设置 $id 键:

{
  "$id": "document",          <-- id for the whole schema
  "type": "object",
  "required": [
    "type",
    "title"
  ],
  "properties": {
    "type": {
      "$id": "document-type", <-- id for the type schema
      "enum": [
        "journal",
        "book",
        "generic"
      ]
    },
    "title": {
      "$id": "document-title", <-- id for the title schema
      "type": "string",
      "minLength": 1,
      "maxLength": 500
    }
  }
}

Ajv 允许您通过其在 Ajv#getSchema 中的 id 引用模式,它将模式编译为验证函数:

const validate_document = ajv.getSchema('document');
const validate_type = ajv.getSchema('document-type');
const validate_title = ajv.getSchema('document-title');

console.log(
    'Is {type: "journal", title: "foo"} valid? '
  , validate_document({type: "journal", title: "foo"})
); // true

console.log(
    'Is "qux" a valid document type? '
  , validate_type("qux")
); // false

console.log(
    'Is "journal" a valid document type? '
  , validate_type("journal")
); // true

console.log(
    'Is "" a valid document title? '
  , validate_title("")
); // false

console.log(
    'Is "foo" a valid document title? '
  , validate_title("foo")
); // true
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/6.11.0/ajv.min.js"></script>
<script>
const ajv = new Ajv;

ajv.addSchema({
  "$id": "document",
  "type": "object",
  "required": [
    "type",
    "title"
  ],
  "properties": {
    "type": {
      "$id": "document-type",
      "enum": [
        "journal",
        "book",
        "generic"
      ]
    },
    "title": {
      "$id": "document-title",
      "type": "string",
      "minLength": 1,
      "maxLength": 500
    }
  }
});

</script>