Json-架构字段存在且具有值

Json-schema field is present and has value

我有这样的架构:

{
  "$schema": "http://json-schema.org/draft-07/schema#",  
  "type": "object",
  "properties": {
    "foo": {
      "enum": [
        "foo1",
        "foo2"
      ]
    },
    "bar": {
      "type": "number"
    },
}

如果 foo 存在并且它的值为“foo1”,我希望 bar 是必需的,否则应该被禁止。我在尝试类似的东西:

"if": {
    "properties": {
      "foo": {
        "const": "foo1"
      }
    }
  },
  "then": {
    "required": [
      "bar"
    ]
  },
  "else": {
    "not": {
      "required": [
        "bar"
      ]
    }
  }

但是,如果 foo 不存在,则需要 bar,而我不希望这样。就好像 if 语句将字段的缺失解释为 true 一样。有没有办法让一个字段只有在另一个可选字段存在且具有特定值时才需要?类似于:

"if": {
  allOf: [
    {
      "properties": {
        "foo": {
          "const": "foo1"
        }
      }
    },
    {
      "contains": "foo"
    }
  ]
}
"then": {
  "required": [
    "bar"
  ]
},
"else": {
  "not": {
    "required": [
      "bar"
    ]
  }
}

顺便说一下,我在这里发现了很多类似的问题,但是 none 不需要 foo。

if/then/else 关键字的值本身就是模式。 如果您单独使用 if 关键字的模式值会怎样?

您会发现,它将成功验证空对象而不会出错。

properties 仅将子模式应用于键匹配的实例位置。如果您的对象没有 foo 属性,则您没有对该对象进行任何验证。

您需要将 required 添加到您的 if 语句中,以便它按您期望的方式工作。

"if": {
    "properties": {
      "foo": {
        "const": "foo1"
      }
    },
    "required": ["foo"]
  }

在此处查看实际效果:https://jsonschema.dev/s/L0rlG

几个小时后,我想出了一个解决方案,我将在此处 post,因为它适用于 json 架构的早期版本,其中 if/then/else 是不可用,因此如果无法升级,可能有人需要它,但我接受了 Relequestual 的回答,因为他的解决方案对于那些拥有最新版本的人来说更优雅

"oneOf":
  [
    {
      "not": {"required": ["foo", "bar"]}
    },
    {
      "required": ["foo"],
      "anyOf": [
        {
          "properties":{
            "foo":{"enum": ["foo1"]}
          },
          "required": ["bar"]
        },
        {
          "properties":{
            "foo": {"not": {"enum": ["foo1"]}}
          },
          "not": {"required": ["bar"]}
        }
      ]}
  ]