jsonschema - 使用 oneOf 的 JSON 模式数组验证问题
问题描述
希望我能在这个验证问题上找到一些帮助:我有一个 JSON 数组,它可以有多种对象类型(视频、图像)。在该数组中,对象具有rel
字段值。我正在处理的情况是,只能有一个"rel": "primaryMedia"
允许的对象——视频或图像。
以下是图像和视频案例的对象表示,均显示"rel": "primaryMedia"
.
{
"media": [
{
"caption": "Caption goes here",
"id": "ncim87659842",
"rel": "primaryMedia",
"type": "image"
},
{
"description": "Shaima Swileh arrived in San Francisco after fighting for 17 months to get a waiver from the U.S. government to be allowed into the country to visit her son.",
"headline": "Yemeni mother arrives in U.S. to be with dying 2-year-old son",
"id": "mmvo1402810947621",
"rel": "primaryMedia",
"type": "video"
}
]
}
这是我创建的架构的精简版本,用于验证这一点oneOf
(假设这将处理我的情况)。然而,它并没有按预期工作。
{
"$id": "http://example.com/schema/rockcms/article.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {},
"properties": {
"media": {
"items": {
"oneOf": [
{
"additionalProperties": false,
"properties": {
"caption": {
"type": "string"
},
"id": {
"type": "string"
},
"rel": {
"enum": [
"primaryMedia"
],
"type": "string"
},
"type": {
"enum": [
"image"
],
"type": "string"
}
},
"required": [
"caption",
"id",
"rel",
"type"
],
"type": "object"
},
{
"additionalProperties": false,
"properties": {
"description": {
"type": "string"
},
"headline": {
"type": "string"
},
"id": {
"type": "string"
},
"rel": {
"enum": [
"primaryMedia"
],
"type": "string"
},
"type": {
"enum": [
"video"
],
"type": "string"
}
},
"required": [
"description",
"headline",
"id",
"rel",
"type"
],
"type": "object"
}
]
},
"type": "array"
}
}
}
使用https://www.jsonschemavalidator.net上的 JSON Schema 验证器,该模式会在数据正确呈现时进行验证,但在尝试捕获错误时不起作用。
在以下情况下,headline
为视频添加了id
. 这应该会失败,因为headline
不允许在视频中使用,并且id
是必需的。
{
"media": [
{
"headline": "Yemeni mother arrives in U.S. to be with dying 2-year-old son",
"rel": "primaryMedia",
"type": "video"
}
]
}
然而,我从验证器获得的结果并不完全是预期的。似乎它在响应中将两个对象模式混为一谈。
除此之外,我还单独发现该模式将允许在 中同时填充视频和图像对象media
,这是意料之中的。
一直试图弄清楚我做错了什么,但我很难过。如果有人提供,将非常感谢一些反馈。提前致谢!
验证者响应:
消息:JSON 对来自“oneOf”的无模式有效。架构路径:#/properties/media/items/oneOf
消息:尚未定义属性“标题”,并且架构不允许其他属性。架构路径:#/properties/media/items/oneOf/0/additionalProperties
消息:枚举中未定义值“视频”。架构路径:#/properties/media/items/oneOf/0/properties/type/enum
消息:对象缺少必需的属性:描述、ID。架构路径:#/properties/media/items/oneOf/1/required
消息:对象缺少必需的属性:标题、id。架构路径:#/properties/media/items/oneOf/0/required
解决方案
您的问题由三个部分组成,但前两个部分是相互关联的,所以我会解决这些问题,尽管它们本身没有“解决方案”。
- 如何验证数组中只有一个对象具有特定键,而其他对象没有。
你不能用 JSON Schema 做到这一点。适用于数组的 JSON Schema 关键字集没有表达“其中一个值必须与模式匹配”的方法,而是适用于数组中的所有项目,或者适用于数组中的特定项目数组(如果items
是数组而不是对象)。
https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.4
- 验证输出不是我所期望的。我希望只看到与
oneOf
我的对象类型相关的失败分支,该对象类型由type
键定义。
JSON Schema 规范(从 draft-7 开始)没有指定任何返回错误的格式,但是就它告诉您的内容而言,您得到的错误结构非常“完整”(并且类似于我们指定错误的方式应该是返回草稿8)。
考虑一下,就您的业务逻辑而言,验证器对您的架构或 JSON 实例一无所知。在验证 JSON 实例时,验证器可能会遍历所有值,并针对所有适用的子模式测试验证规则。查看您的错误,其中的两个模式oneOf
都适用于数组中的所有项目,因此所有项目都经过验证。如果一个不满足条件,其他的也将被测试。验证器在使用 a 时无法知道oneOf
您的意图是什么。
您可以通过使用if
/then
组合来解决此问题。如果您的if
架构只是该类型的 const,并且您的then
架构是完整的对象类型,您可能会得到更清晰的错误响应,但我没有测试过这个理论。
- 我希望数组中的所有项目都是其中一种类型。这里发生了什么?
从规格...
items
:
如果“items”是一个模式,则如果数组中的所有元素都成功地针对该模式进行验证,则验证成功。
oneOf
:
如果实例针对此关键字值
定义的一个模式成功验证,则该实例针对此关键字成功验证
。
您所做的是说:数组中的每个项目都应该根据 [schemaA] 有效。SchemA:根据以下模式之一,对象应该是有效的:[ oneOf
] 中的模式。
当您认为“项目必须是以下项目之一”时,我可以看到这是多么令人困惑,但是items
将值模式独立地应用于数组中的每个项目。
为了实现你的意思,移动oneOf
上面的items
,然后将其中一种媒体类型重构为另一种项目模式。
这是一个 sudo 模式。
oneOf: [items: properties: type: const: image], [items: properties: type: image]
如果有任何不清楚或您有任何后续问题,请告诉我。
推荐阅读
- java - 数据初始化在 Spring Boot Hibernate 应用程序中不起作用
- swift - Swift重写init(格式:字符串,_参数:CVarArg ...)
- html - Bootstrap,拉伸最后一列
- c - 在c中选择n个输入的元素而不使用数组
- python - 使用 sklearn 的 roc_auc_score 进行 OneVsOne 多分类?
- flutter - 让 Zara 像产品页面一样扑腾扑扑
- javascript - 即使集合不存在使用 node.js 和 mongoose 更新 Mongo DB 中的数据
- python-3.x - 在 Google-Colab 中提取 tar.gz 文件时遇到问题
- php - PHP 示例中使用 API 的两个签名者
- c - 编译后的 C 代码无法执行。拒绝访问