希望我能在这个验证问题上找到一些帮助:我有一个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"
}
}
}
在上使用JSON模式验证器https://www.jsonschemavalidator.net,模式在数据正确呈现时进行验证,但在试图捕捉错误时不起作用。
在下面的情况中,为视频添加了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
消息:尚未定义属性"headline",架构不允许其他属性。架构路径:#/properties/media/items/oneOf/0/additionalProperties
消息:枚举中未定义值"video"。架构路径:#/properties/media/items/oneOf/0/properties/type/enum
消息:对象缺少必需的属性:description,id。架构路径:#/properties/media/items/oneOf/1/必需
消息:对象缺少必需的属性:caption,id。架构路径:#/properties/media/items/oneOf/0/必需
您的问题由三部分组成,但前两部分是链接的,所以我将解决这些问题,尽管它们没有"解决方案";像这样的
- 如何验证数组中只有一个对象具有特定键,而其他对象没有
您无法使用JSON架构执行此操作。适用于数组的JSON模式关键字集不具有表示";其中一个值必须匹配模式";,而是适用于数组中的所有项目或数组中的特定项目(如果items
是与对象相对的数组)。https://datatracker.ietf.org/doc/html/draft-handrews-json-schema-validation-01#section-6.4
- 验证输出不是我所期望的。我希望只看到
oneOf
的失败分支,它与我的对象类型有关由CCD_ 12密钥定义
JSON模式规范(截至draft-7)没有指定任何返回错误的格式,但是您得到的错误结构非常"漂亮";完整的";就它告诉您的内容而言(类似于我们为draft-8指定应返回的错误)。
考虑一下,验证器对您的模式或JSON实例的业务逻辑一无所知。在验证JSON实例时,验证器可以遍历所有值,并针对所有适用的子模式测试验证规则。看看您的错误,oneOf
中的两个模式都适用于数组中的所有项,因此所有项都经过了验证测试。如果其中一个不满足条件,其他人也将接受测试。在使用oneOf
时,验证器无法知道您的意图是什么。
您可以通过使用if
/then
组合来解决此问题。如果您的if
模式只是类型的常量,而then
模式是完整的对象类型,那么您可能会得到更干净的错误响应,但我还没有测试过这个理论。
- 我希望数组中的所有项都是其中一种类型。这是怎么回事
根据规范…
items
:
如果"项目";是一个架构,如果数组根据该架构成功验证。
oneOf
:
如果实例
仅针对该
关键字的值定义的一个架构成功验证,则实例将针对该关键字成功验证。
您所做的是:数组中的每个项都应该根据[schemaA]有效。SchemA:根据以下模式之一,对象应该是有效的:[oneOf
]中的模式。
当你认为";项目必须是以下";,但是CCD_ 22独立地将值模式应用于数组中的每个项。
要实现您的意思,请将oneOf
移到items
之上,然后将其中一个媒体类型重构为另一个项模式。
这是一个sudo模式。
oneOf: [items: properties: type: const: image], [items: properties: type: image]
如果有任何不清楚的地方,或者你有任何后续问题,请告诉我。