首页 > 解决方案 > 如果我使用 JSON Schema 的 if-else 条件,是否有办法针对 JSON 中存在的任何附加键引发错误?

问题描述

我有一个用例,我想检查 JSON 中存在的键,具体取决于不同键的值。

示例 JSON-1:

{ 
  "key_name" : "value1",
  "foo" : "random_value1"
}

示例 JSON-2:

{ 
  "key_name" : "value2",
  "bar" : "random_value2"
}

根据这些例子,

规则 1。如果“key_name”的值为“value1”,那么JSON 中应该只有“foo”键。

规则 2。如果“key_name”的值为“value2”,那么JSON 中应该只有“bar”键。

我编写了以下 JSON Schema 来验证这些 JSON:

{
  "type": "object",
  "properties": {
    "key_name": {
      "type": "string",
      "enum": [
        "value1",
        "value2"
      ]
    },
    "foo": {
      "type": "string"
    },
    "bar": {
      "type": "string"
    }
  },
  "required": [
    "key_name"
  ],
  "additionalProperties": false,
  "allOf": [
    {
      "if": {
        "properties": {
          "key_name": {
            "enum": [
              "value1"
            ]
          }
        }
      },
      "then": {
        "required": [
          "foo"
        ]
      }
    },
    {
      "if": {
        "properties": {
          "key_name": {
            "enum": [
              "value2"
            ]
          }
        }
      },
      "then": {
        "required": [
          "bar"
        ]
      }
    }
  ]
}

现在,根据规则,以下 JSON 无效,应该引发错误。

{ 
  "key_name" : "value1",
  "foo" : "random_value1",
  "bar" : "random_value2"
}

或者

{ 
  "key_name" : "value2",
  "bar" : "random_value2",
  "foo" : "random_value"
}

但是,上面的 JSON Schema 没有这样做。它仅根据“key_name”的值检查“foo”/“bar”键是否。它无法检查是否存在任何新密钥。

怎么办?

标签: jsonjsonschemajson-schema-validatorpython-jsonschema

解决方案


这已经在这里得到了回答:互斥的属性组

此外,您可以在此处找到一个很好的概述:jsonSchema attribute conditionally required


对于您的具体示例,可以想到以下方法:

  1. 添加"not": { "required": ["bar"] }到您的第一个then子句以表明这"bar"是不允许的。然后"foo"在第二then个子句中也是如此。
  2. 如果总是只"key_name"允许一个其他属性,您也可以简单地添加"maxProperties": 2主模式。

编辑(以解决白名单替代方案):

另一种选择是像这样分别定义每个排列:

{
  "oneOf": [
    {
      "type": "object",
      "properties": {
        "key_name": { "const": "value1" },
        "foo": { "type": "string" }
      },
      "required": ["key_name", "foo"],
      "additionalProperties": false
    },
    {
      "type": "object",
      "properties": {
        "key_name": { "const": "value2" },
        "bar": { "type": "string" }
      },
      "required": ["key_name", "bar"],
      "additionalProperties": false
    }
  ]
}

推荐阅读