我正在尝试根据允许的模式验证具有不同嵌套
$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 应该处理它。
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
,您应该会得到预期的结果。