【问题标题】:Validate using a specific definition with ajv使用带有 ajv 的特定定义进行验证
【发布时间】:2020-09-15 16:13:56
【问题描述】:

我有一个描述我的 API 的 JSON 模式文件。它包含一些定义以及我想忽略的 codegen 中的一些残留部分(propertiesrequired 字段):

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "CreateBook": {
      "properties": {
        "title": {"type": "string"},
        "author": {"type": "string"},
        "numPages": {"type": "number"}
      },
      "required": ["title", "author"]
    },
    "CreateShelf": {
      "properties": {
        "books": {"type": "array", "items": {"type": "string"}}
      },
      "required": ["books"]
    }
  },
  "properties": {
    "/api/create-book": {
      "properties": {"type": {"post": {"$ref": "#/definitions/CreateBook"}}},
      "required": ["post"],
      "type": "object"
    },
    "/api/create-shelf": {
      "properties": {"type": {"post": {"$ref": "#/definitions/CreateShelf"}}},
      "required": ["post"],
      "type": "object"
    }
  },
  "required": ["/api/create-book", "/api/create-shelf"],
  "type": "object"
}

我想根据定义验证请求。我想完全忽略 propertiesrequired 字段,它们描述了 API 本身的形状,而不是单个请求。

鉴于我期望的 CreateBook 请求和这个 JSON 模式,我应该如何验证它?

这是我尝试过的:

const ajv = new Ajv();
const validate = ajv.compile(jsonSchema);

const body = {
  author: 'Roald Dahl',
  numPages: 234,
  // missing title
};

if (!validate(body, '#/definitions/CreateBook')) {
  console.log(validate.errors);
}

此日志:

[
  {
    keyword: 'required',
    dataPath: '#/definitions/CreateBook',
    schemaPath: '#/required',
    params: { missingProperty: '/api/create-book' },
    message: "should have required property '/api/create-book'"
  }
]

所以它忽略了dataPath 参数('#/definitions/CreateBook')。这样做的正确方法是什么?我需要为每种请求类型创建一个新架构吗?

【问题讨论】:

    标签: jsonschema ajv


    【解决方案1】:

    如果你使用addSchema而不是compile来编译架构,你可以指定一个片段。

    const ajv = new Ajv();
    ajv.addSchema(jsonSchema);
    const validate = ajv.getSchema("#/definitions/CreateBook");
    
    const body = {
      author: 'Roald Dahl',
      numPages: 234,
      // missing title
    };
    
    if (!validate(body)) {
      console.log(validate.errors);
    }
    

    【讨论】:

    • 看起来$id 不是必需的,ajv.getSchema('#/definitions/CreateBook') 工作正常。由于validate 特定于CreateBook,我认为最后一行validate 的第二个参数是没有意义的。一次有多个验证器(每个端点一个)可以吗?我相信 ajv 会跟踪 ajv 对象本身的某些状态,所以我可以想象这会造成麻烦。
    • 啊,我猜你不需要$id,除非你需要添加多个模式。是的,验证函数的额外参数不正确。我正在修改您的原始代码,但我错过了那个。我将编辑答案以解决这些问题。
    • “一次有很多验证者可以吗”。是的,没关系。如果您需要添加多个模式,则需要给它们$ids 以区分它们。此外,一旦编译了验证器,它就只是一个独立的函数,不再依赖于 ajv 状态。
    猜你喜欢
    • 2017-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-25
    • 2016-08-23
    • 1970-01-01
    相关资源
    最近更新 更多