繁体   English   中英

JSON 没有要求的模式之一

[英]JSON Schema oneof without required

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"
    }
  ]
}

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

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

我会添加一个带有嵌套allOfoneOf

{
  ...
  "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失败了

您可以在此处测试这些解决方案

这里有几个选项可以添加到@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"] } }
  }
]

我不得不尝试为 3 个字段解决这个问题,其中字段 1 也是可选的。 这样做揭示了@gregdennis 对解决方案 3的回答比它需要的略多,这实现了相同的目标,因为不需要检查所需的单个值,因为两者都不需要。

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

要为 3 执行此操作,它看起来像:

{
  ...
  "not": {
    "anyOf": [{
      "required": ["field_1", "field_2", "field_3"]
    },
    {
      "required": ["field_1", "field_2"]
    },
    {
      "required": ["field_2", "field_3"]
    },
    {
      "required": ["field_1", "field_3"]
    }]
  }
  ...
}

随着您添加更多字段,这显然变得不那么有用。 因此,有空间去 N 的更好解决方案如下:

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

你可以在这里玩。

您可以按如下方式执行此操作:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "field_1": {
      "type": "string"
    }
  },
  "oneOf": [
    {
      "properties": {

      },
      "additionalProperties": false
    },
    {
      "properties": {
        "field_2": {
          "type": "string"
        }
      },
      "required": ["field_2"],
      "additionalProperties": false
    },
    {
      "properties": {
        "field_3": {
          "type": "string"
        }
      },
      "required": ["field_3"],
      "additionalProperties": false
    }
  ],
  "required": [
    "field_1"
  ]
}

本书所述:“oneOf: (XOR) 必须对其中一个子模式有效”。

  1. 我将 field_1 添加到“主”模式并根据需要标记此字段。
  2. 我描述了三个子模式。
  • 没有必填字段的第一个模式。
  • 具有必需的“field_2”字段的第二个模式。
  • 具有必需的“field_3”字段的第三个模式。
  1. 对于所有子模式,我将“additionalProperties”设置为值false

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM