【问题标题】:JSON Schema oneof without requiredJSON Schema oneof 不需要
【发布时间】:2020-06-09 16:32:41
【问题描述】:

JSON Schema 草案 7 或 8 中,正确的说法是,我们想要选择其中一个属性,但不能同时选择两者。我可以使用required 关键字进行构造,但是您必须包含任何一个必需的属性。这是我能想到的,对吗?

在此示例中,我试图验证 field_1 是必需的,并且我们需要 field_2field_3 中的任何一个或都不需要。 (见例子)

{
  "$schema": "http://json-schema.org/draft-08/schema#",
  "type": "object",
  "properties": {
    "field_1": {
      "type": "string"
    },
    "field_2": {
      "type": "string"
    },
    "field_3": {
      "type": "string"
    }
  },
  "required": [
    "field_1"
  ],
  "oneof": [
    {
      "properties": [
        "field_2"
      ]
    },
    {
      "properties": [
        "field_3"
      ]
    }
  ],
  "additionalProperties": false,
  "examples": [
    {
      "field_1": "1",
      "field_2": "2"
    },
    {
      "field_1": "1",
      "field_3": "3"
    },
    {
      "field_1": "1"
    }
  ]
}

【问题讨论】:

    标签: json validation schema jsonschema


    【解决方案1】:

    [已编辑 - 请参阅下面的第三个解决方案]

    解决方案 1 - 至少一个,但不是两个(详细)

    我会添加一个带有嵌套oneOfallOf

    {
      ...
      "allOf": [
        {
          "oneOf": [
            {"required": ["field_2"]},
            {"required": ["field_3"]}
          ],
        },
        {
          "not": {
            "required": ["field_2", "field_3"]
          }
        }
      ],
      ...
    }
    

    这要求两个字段之一存在,但不能同时存在。


    解决方案 2 - 至少一个,但不是两个

    我认为这可以通过仅使用oneOf 来进一步简化:

    {
      ...
      "oneOf": [
        {"required": ["field_2"]},
        {"required": ["field_3"]}
      ],
      ...
    }
    
    • 如果两者都不存在,那么它们都会失败,oneOf 也会失败。
    • 如果有,则oneOf 通过。
    • 如果两者都存在,那么这两个都会通过,oneOf 会失败。

    是的,这样更好。看看你所拥有的,我认为这就是你想要做的,所以你真的很接近!


    解决方案 3 - 最多一个

    要在两个字段都不存在时通过,您需要第一个解决方案,但将 allOf 更改为 anyOf

    {
      ...
      "anyOf": [
        {
          "oneOf": [
            {"required": ["field_2"]},
            {"required": ["field_3"]}
          ],
        },
        {
          "not": {
            "required": ["field_2", "field_3"]
          }
        }
      ],
      ...
    }
    
    • 如果两者都不存在,则 not 子模式将通过,anyOf 将通过。
    • 如果存在,则 oneOf 子模式将通过,anyOf 将通过。
    • 如果两者都存在,那么
      • oneOf 两个子模式都会通过,所以 oneOf 失败
      • not 子模式将失败
      • 所以anyOf 失败

    您可以测试这些解决方案here

    【讨论】:

    • 我的一个要求是即使field_2field_3 都不存在,它也应该通过,我没有看到第二个解决方案通过了这个。在您的第一个解决方案中,我觉得allof 块中的两个条件是矛盾的。任何 cmets...
    • 我已经编辑了答案以适应“两者都不”的要求。
    • 感谢您的第三个解决方案工作正常。虽然有点冗长,但 Jason 的依赖项解决方案也很方便。我意识到有多种方法可以实现这一目标。
    • 使用 JSON Schema 有多种方法可以实现大多数事情?
    【解决方案2】:

    这里还有几个选项可以添加到@gregdennis 的答案中。

    依赖关系

    这是dependencies 关键字的一个很好的用例。这就是说,“如果有一个“field_2”,就不可能有一个“field_3”,并且,“如果有一个“field_3”,就不可能有一个“field_2”。如果“field_2”或“field_3”都不存在,则不应用任何约束并且架构通过。

    "dependencies": {
      "field_2": { "not": { "required": ["field_3"] } },
      "field_3": { "not": { "required": ["field_2"] } }
    }
    

    最大属性

    这个有点老套,但它的好处是可以成为单线。如果需要“field_1”并且只允许“field_2”或“field_2”其中之一,则此对象中的属性不能超过两个。当心,这个解决方案可能比它的价值更聪明。由于此约束间接起作用,因此可能会导致将来的维护困难。

    "maxProperties": 2
    

    如果/那么

    这只是 dependencies 选项的更详细版本,但对于阅读架构的人来说可能更具描述性。

    "allOf": [
      {
        "if": { "required": ["field_2"] },
        "then": { "not": { "required": ["field_3"] } }
      },
      {
        "if": { "required": ["field_3"] },
        "then": { "not": { "required": ["field_2"] } }
      }
    ]
    

    【讨论】:

    • 太棒了,我真的很喜欢依赖项解决方案。我相信它清楚地传递了信息。 allof,oneof 解决方案有点冗长。
    • 请注意,对于 2019-09 及更高版本的草稿,此用法中的 dependencies 已更改为 dependentProperties
    • @gregsdennis 感谢您的更新,我只检查changelogdependentSchemas 而不是dependentProperties
    • 没有任何dependentPropertiesdependencies 已替换为 dependentSchemasdependentRequired 关键字。见json-schema.org/draft/2019-09/json-schema-validation.html的附录A
    猜你喜欢
    • 2017-06-24
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 2019-04-23
    • 1970-01-01
    • 2014-09-20
    • 2022-01-14
    • 1970-01-01
    相关资源
    最近更新 更多