JSON模式条件语句

时间:2019-11-19 06:45:23

标签: json jsonschema json-schema-validator

我正在尝试验证我认为是一个简单的JSON模式作为Python应用程序的配置文件,它是标头键/值对的列表,唯一的麻烦是,如果“类型”字段设置为“ AnyValue”,则不需要键值。

以下是架构:

{
    "definitions":
    {
        'KeyEntry':
        {
             "properties":
             {
                'Type': {"type" : "string"},
                'Key': {"type": "string"}
             },
             "required": ['Type', 'Key'],
            "anyOf":
            [
                {
                    "if":
                    {
                        "properties": {'Type': {"const": 'ExactValue'}}
                    },
                    "then":
                    {
                        "properties":
                        {
                            'Value': {"type": "string"}
                        },
                        "required": ['Type', 'Key', 'Value'],
                        "additionalProperties": false
                    }
                },
                {
                    "if":
                    {
                        "properties": {'Type': {"const": 'AnyValue'}}
                    },
                    "then":
                    {
                        "required": ['Type', 'Key'],
                        "additionalProperties": false
                    }
                }
            ]
        }
    },

    "type": "object",
    "properties":
    {
        'Keys':
        {
            "type": "array",
            "items": {"$ref": "#/definitions/KeyEntry"}
        }
    },
    "required": ['Keys']
}

大多数验证有效,除非我添加了额外的值,即使我在整个模式中设置了“ additionalProperties”:false。

以下是接受额外值的示例:

{
    "Keys": [

        {
            "Type": "AnyValue",
            "Key": "Version",
            "Y": "Yes",
            "N": "No",
        }
    ]
}

请有人帮忙解释我哪里出了问题以及如何纠正它吗?

1 个答案:

答案 0 :(得分:2)

additionalProperties draft-07 ...

  

具有“ additionalProperties”的验证仅适用于实例名称的子值,这些实例名称与“ properties”中的任何名称都不匹配,并且与“ patternProperties”中的任何正则表达式都不匹配。

这意味着additionalProperties仅知道出现在properties中或与patternProperties中的正则表达式匹配的关键字。在没有additionalProperties的情况下将requiredproperties一起使用将创建一个过时的架构(没有任何东西会通过验证)。

相反,您可以将关注点分离为实际需要的内容...

  • 您希望类型,键和值全部为字符串。 之一...
  • 如果类型为AnyValue,则仅需要类型和密钥。
  • 如果类型为ExactValue,则需要类型,键和值。

这也更容易理解。这是live demo with your data

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "KeyEntry": {
      "properties": {
        "Type": {
          "type": "string"
        },
        "Key": {
          "type": "string"
        },
        "Value": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "required": [
        "Type",
        "Key"
      ],
      "anyOf": [
        {
          "if": {
            "properties": {
              "Type": {
                "const": "ExactValue"
              }
            }
          },
          "then": {
            "required": [
              "Type",
              "Key",
              "Value"
            ]
          },
          "else": false
        },
        {
          "if": {
            "properties": {
              "Type": {
                "const": "AnyValue"
              }
            }
          },
          "then": {
            "required": [
              "Type",
              "Key"
            ]
          },
          "else": false
        }
      ]
    }
  },
  "type": "object",
  "properties": {
    "Keys": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/KeyEntry"
      }
    }
  },
  "required": [
    "Keys"
  ]
}