如何使用 ajv 验证具有不同嵌套 $schema 值的数据?

问题描述 投票:0回答:1

我正在尝试根据允许的模式验证具有不同嵌套

$schema
值的数据,但它无法使用正确的子模式正确验证嵌套对象。

这是一个简化的示例:

const ajv = new Ajv();

const mainSchema = {
  $id: "mainSchema",
  type: "object",
  properties: {
    foo: {
      anyOf: [{ $ref: "intSchema" }, { $ref: "strSchema" }],
    },
  },
};
const intSchema = {
  $id: "intSchema",
  type: "object",
  properties: {
    value: {
      type: "integer",
    },
  },
};
const strSchema = {
  $id: "strSchema",
  type: "object",
  properties: {
    value: {
      type: "string",
    },
  },
};

const dataA = {
  $schema: "mainSchema",
  foo: {
    $schema: "intSchema",
    value: 42,
  },
};

const dataB = {
  $schema: "mainSchema",
  foo: {
    $schema: "strSchema",
    value: 1,
  },
};

const dataC = {
  $schema: "mainSchema",
  foo: {
    $schema: "unknownSchema",
    value: false,
  },
};

ajv.addSchema([intSchema, strSchema]);
const validate = ajv.compile(mainSchema);
console.log(validate(dataA)); // true
console.log(validate(dataB)); // true
console.log(validate(dataC)); // false
当我期望

dataA

 返回 false 时,
dataB
true
都返回
validate(dataB)
。我认为它会使用数据中的
$schema
值来根据添加的模式以及相应的
$id
来验证对象。

我可以创建一个函数来逐步遍历每个数据对象,并使用

$id
属性根据相应的模式验证它(如果这是完成此操作的唯一方法),但我认为 ajv 应该处理它。

jsonschema json-schema-validator ajv
1个回答
0
投票

dataB
true
因为它满足
anyOf
您定义的模式。验证者不考虑使用
$schema
来识别应使用哪个
$id
进行验证。它只知道您使用
addSchema
方法加载到注册表中的架构。

您在数据实例中使用

$schema
将被忽略,因为您尚未在架构定义中约束该属性。通常,您仅在架构本身中使用
$schema
,而不是实例。但这是争论的热点话题。 JSON Schema 规范中未定义它。

我所说的“不受约束”的意思如以下模式所示,这将使您的所有模式在使用 $schema 作为实例中的附加属性时失效。

const mainSchema = {
  $id: "mainSchema",
  type: "object",
  properties: {
    foo: {
      anyOf: [{ $ref: "intSchema" }, { $ref: "strSchema" }],
    },
  },
};
const intSchema = {
  $id: "intSchema",
  type: "object",
  additionalProperties: false,
  properties: {
    value: {
      type: "integer",
    },
  },
};
const strSchema = {
  $id: "strSchema",
  type: "object",
  additionalProperties: false,
  properties: {
    value: {
      type: "string",
    },
  },
};

对于 
anyOf

,如果至少一个模式返回

true
结果,则该实例被视为有效。尝试使用
oneOf
,您应该会得到预期的结果。
    

© www.soinside.com 2019 - 2024. All rights reserved.