Json-schema required/non-required & 字段的允许值取决于其他字段的值

Json-schema required/non-required & allowed valeus for fields depend on the values of other fields

我有三个字段,foo、bar、baz。 bar 依赖于 foo,baz 依赖于 bar:

  1. foo 是布尔值
  2. 如果没有提供 foo,禁止使用 bar 和 baz
  3. foo = true: bar 是必需的枚举值 bar1 和 bar2
  4. foo = false: bar & baz 被禁止
  5. foo = true & bar = bar1: baz 是必填对象,必填字段 baz1 和非必填字段 baz2 均为 string
  6. foo = true & bar = bar2: baz 是必填对象,具有必填字段 baz3 string

所以我开始迭代构建它。到目前为止,我有

{
  "$schema": "http://json-schema.org/draft-07/schema#",  
  "type": "object",
  "properties": {
    "foo": {
      "type": "boolean"
    }
  },
  "allOf": [
    {
      "if": {
        "not": {
          "required": ["foo"]
        }
      },
      "then": {
        "not": {
          "required": ["bar", "baz"]
        }
      }
    },
    {
      "if": {
        "properties": {
          "foo": {
            "const": true
          }
        },
        "required": ["foo"]
      },
      "then": {
        "properties": {
          "bar": {
            "enum": ["bar1", "bar2"]
          }
        },
        "required": ["bar"]
      }
    },
    {
      "if": {
        "properties": {
          "foo": {
            "const": false
          }
        },
        "required": ["foo"]
      },
      "then": {
        "not": {
          "required": ["bar", "baz"]
        }
      }
    },
    {
      "if": {
        "properties": {
          "bar": {
            "const": "bar1"
          }
        },
        "required": ["bar"]
      },
      "then": {
        "properties": {
          "baz": {
            "type": "object",
            "properties": {
              "baz1": { "type": "number" },
              "baz2": { "type": "string" }
            },
            "required": ["baz1", "baz2"],
            "additionalProperties": false
          }
        },
        "required": ["baz"]
      }
    },
    {
      "if": {
        "properties": {
          "bar": {
            "const": "bar2"
          }
        },
        "required": ["bar"]
      },
      "then": {
        "properties": {
          "baz": {
            "type": "object",
            "properties": {
              "baz3": { "type": "number" },
              "baz4": { "type": "string" }
            },
            "required": ["baz3", "baz4"],
            "additionalProperties": false
          }
        },
        "required": ["baz"]
      }
    }
  ]
}

它正确地验证了我迄今为止尝试过的所有组合,除非 baz 存在时没有 foo & bar 或 foo = false & no bar,这两种组合都验证为真,即使我认为它是假的如果不需要 foo 并且 foo 为假,则 bar 和 baz 都设置为不需要。我错过了什么?

您应该拆分 required 子句,以便它们一次检查一个关键字。

如果 'bar' 和 'baz' 都不存在,

"required": ["bar", "baz"] 将为 false,这是您想要的,但如果 属性 存在,它也将为 false另一个不是,另一个不是(因为您随后用“不”包装了该支票,使“如果”条件为真)。

因此,将该检查更改为:

"allOf": [
  { "required": ["bar"] },
  { "required": ["baz"] }
]

根据 Ether 的回答,我得到了这个,它似乎按预期工作,所以我提供它是为了方便将来可能需要它的任何人参考:

  "$schema": "http://json-schema.org/draft-07/schema#",  
  "type": "object",
  "properties": {
    "foo": {
      "type": "boolean"
    }
  },
  "allOf": [
    {
      "if": {
        "not": {
          "required": ["foo"]
        }
      },
      "then": {
        "allOf": [
          {
            "not": {
              "required": ["bar"]
            }
          },
          {
            "not": {
                "required": ["baz"]
            }
          }
        ]
      }
    },
    {
      "if": {
        "properties": {
          "foo": {
            "const": true
          }
        },
        "required": ["foo"]
      },
      "then": {
        "properties": {
          "bar": {
            "enum": ["bar1", "bar2"]
          }
        },
        "required": ["bar"]
      }
    },
    {
      "if": {
        "properties": {
          "foo": {
            "const": false
          }
        },
        "required": ["foo"]
      },
      "then": {
        "allOf": [
          {
            "not": {
              "required": ["bar"]
            }
          },
          {
            "not": {
                "required": ["baz"]
            }
          }
        ]
      }
    },
    {
      "if": {
        "properties": {
          "bar": {
            "const": "bar1"
          }
        },
        "required": ["bar"]
      },
      "then": {
        "properties": {
          "baz": {
            "type": "object",
            "properties": {
              "baz1": { "type": "number" },
              "baz2": { "type": "string" }
            },
            "required": ["baz1", "baz2"],
            "additionalProperties": false
          }
        },
        "required": ["baz"]
      }
    },
    {
      "if": {
        "properties": {
          "bar": {
            "const": "bar2"
          }
        },
        "required": ["bar"]
      },
      "then": {
        "properties": {
          "baz": {
            "type": "object",
            "properties": {
              "baz3": { "type": "number" },
              "baz4": { "type": "string" }
            },
            "required": ["baz3", "baz4"],
            "additionalProperties": false
          }
        },
        "required": ["baz"]
      }
    }
  ]
}