JSON Schema 嵌套 If Then

3

我似乎找不到一种可行的方法在枚举上应用多个if/then逻辑。

anyOf 不应用条件逻辑,而是说如果其中任何一个匹配就可以了。

allOf 同样不适用条件逻辑,但测试属性/必需字段的超集。

这是一个JSON Schema示例:

{
  "definitions": {},
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/root.json",
  "type": "object",
  "title": "The Root Schema",
  "required": [
    "type"
  ],
  "properties": {
    "type": {
      "$id": "#/properties/type",
      "enum": [
        "a",
        "b",
        "c"
      ],
      "title": "The Type"
    },
    "options": {
      "$id": "#/properties/options",
      "type": "object",
      "title": "The Options Schema",
      "oneOf": [
        {
          "if": { "properties": { "type": { "const": "a" } }
          },
          "then": {
            "required": [ "option1" ],
            "properties": {
              "option1": {
                "$id": "#/properties/options/properties/option1",
                "type": "boolean",
                "title": "The option1 Schema"
              }
            }
          }
        },
        {
          "if": { "properties": { "type": { "const": "b" } }
          },
          "then": {
            "required": [ "option2" ],
            "properties": {
              "option2": {
                "$id": "#/properties/options/properties/option2",
                "type": "boolean",
                "title": "The option2 Schema"
              }
            }
          }
        },
        {
          "if": { "properties": { "type": { "const": "c" } }
          },
          "then": {
            "required": [],
            "properties": {}
          }
        }
      ]
    }
  }
}

如果您对以下JSON进行验证:
{
  "type": "a",
  "options": {
    "option1": true
  }
}

由于需要option2,所以它失败了。

如果您将其更改为anyOf,则会成功,但如果将JSON更改为无效,则会失败:

{
  "type": "a",
  "options": {
    "option2": false
  }
}

它仍然成功。

我还没有成功地实现嵌套的if/then/else/if/then/else语句。

我如何执行检查,在每个type中设置一组属性,而你不能混合使用它们?这真的可能吗,还是我应该改变我的设计呢?

1个回答

2
首先,您可以在此处测试您的模式。互联网上有几个这样的网站。
其次,if/then/else构造引入以替换这种枚举情况下的oneOf,而不是与之组合使用。
这个子模式
"if": { "properties": { "type": { "const": "a" } } },
"then": {
  "required": [ "option1" ],
  "properties": {
    "option1": {
      "$id": "#/properties/options/properties/option1",
      "type": "boolean",
      "title": "The option1 Schema"
    }
  }
}

type不是a时,实际上不会失败。它只是说,如果type=a,则应用then子模式。它并没有说明如果type不是a,要验证什么,因此它通过了。如果你在这里添加一个else:false,它将更符合你的想法,但我鼓励你以不同的方式思考。
使用oneOfif/then/else,但不要同时使用两者。我建议修改你的子模式以使用以下格式:
{
  "properties": {
    "type": { "const": "a" },
    "option1": {
      "$id": "#/properties/options/properties/option1",
      "type": "boolean",
      "title": "The option1 Schema"
    }
  },
  "required": [ "option1" ],
}

这段话表明option1是必需的,必须是一个布尔值,并且type=a。如果type不是a,则此模式将失败,这正是您想要的。 此答案更详细地描述了您需要做的事情。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接