使用oneOf

时间:2019-02-05 13:07:58

标签: jsonschema json-schema-validator

希望我可以找到有关此验证问题的帮助:我有一个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模式验证器,该模式将验证何时正确显示数据,但是在尝试捕获错误时该模式不起作用。

在以下情况下,为视频添加了{​​{1}},但缺少了headline。这应该会失败,因为视频中不允许使用id,并且需要headline

id

但是,我并不是完全希望从验证器获得的结果。似乎它在响应中合并了两个对象模式。

除此之外,我还单独发现该模式将允许{ "media": [ { "headline": "Yemeni mother arrives in U.S. to be with dying 2-year-old son", "rel": "primaryMedia", "type": "video" } ] } 中同时包含视频和图像对象。

曾经试图弄清楚我做错了什么,但是很沮丧。如果有人提供的话,将不胜感激。预先感谢!


验证者响应:

消息:JSON对'oneOf'中的任何模式均无效。 架构路径:#/ properties / media / items / oneOf

消息:尚未定义属性“标题”,并且该架构不允许其他属性。 架构路径:#/ properties / media / items / oneOf / 0 / additionalProperties

消息:枚举中未定义值“视频”。 架构路径:#/ properties / media / items / oneOf / 0 / properties / type / enum

消息:对象:描述,标识缺少必需的属性。 架构路径:#/ properties / media / items / oneOf / 1 /必填

消息:对象:标题,ID缺少必需的属性。 架构路径:#/ properties / media / items / oneOf / 0 / required

1 个答案:

答案 0 :(得分:0)

您的问题由三部分组成,但是前两部分是链接的,因此我将解决这些问题,尽管它们没有这样的“解决方案”。

  
      
  1. 如何验证数组中只有一个对象具有特定键,而其他对象则没有。
  2.   

您无法使用JSON模式执行此操作。 适用于数组的JSON模式关键字集没有一种表示“其中一个值必须与模式匹配”的方法,而是适用于数组中的所有项或数组中的SPECIFIC项数组(如果items是一个与对象相对的数组)。 https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.4

  
      
  1. 验证输出不是我期望的。我希望只看到与我的对象类型相关的oneOf失败的分支   由type键定义。
  2.   

JSON Schema规范(从草案7开始)并未指定任何返回错误的格式,但是就所显示的内容而言,您得到的错误结构相当“完整”(类似于我们所指定的方式)错误应返回至草稿8)。

考虑一下,根据您的业务逻辑,验证器对您的模式或JSON实例一无所知。 验证JSON实例时,验证器可以逐步检查所有值,并针对所有适用的子方案测试验证规则。查看您的错误,oneOf中的两个模式都适用于您数组中的所有项目,因此都对所有模式进行了验证测试。如果其中一个不满足条件,则还将对其他人进行测试。验证者在使用oneOf时无法知道您的意图。

通过使用if / then组合,您也许可以解决此问题。如果您的if模式仅仅是该类型的const,而您的then模式是完整的对象类型,则您可能会得到更清晰的错误响应,但我尚未测试该理论。

  
      
  1. 我希望数组中的所有项目成为其中一种类型。这是怎么回事?
  2.   

根据规格...

items

  

如果“ items”是模式,则如果   阵列针对该架构成功验证。

oneOf

  

实例是否可以针对此关键字成功验证
  完全针对此定义的一个架构成功验证了
  关键字的值。

您说的是:根据[schemaA],数组中的每个项目都应有效。方案:对象应根据以下架构中的一个有效:[oneOf内部的架构]。

当您认为“项目必须是以下项目之一”时,我可以看到这令人困惑,但是items将值模式独立地应用于数组中的每个项目。

要使其按照您的意思工作,请将oneOf移到items上方,然后将其中一种媒体类型重构为另一项架构。

这是一个sudo模式。

oneOf: [items: properties: type: const: image], [items: properties: type: image]

如果其中任何一个不清楚或有任何后续问题,请告诉我。