jsonschema 验证没有按预期返回错误?

jsonschema validation not returning error as expected?

我正在使用这个模式,我希望使用基于值的条件模式。

If app_name is "test" then property name should be required.

if app_name if "rest" then property ips should be required.

{
    "type": "object",
    "oneOf": [
        {
            "properties": {
                "app_name": {"enum": ["test"]}
            },
            "required": ["name"]
        },
        {
            "properties": {
                "app_name": {"enum": ["rest"]}
            },
            "required": ["ips"]
        },
    ],
    "properties": {
        "name": {"type": "string"},
        "ips": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": True,
            "items": {
                "type": "string",
                "pattern": "[^ ]",
                "minLength": 1,
                "maxLength": 50
            }
        },
        "app_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10,
            "enum": [
                "test",
                "rest"
            ]
        }
    },
    "required": [
        "app_name"
    ]
}

我正在使用以下代码

formatted_data = {"app_name": "rest", "name": "test data"}
print jsonschema.exceptions.best_match(jsonschema.Draft4Validator(schema).iter_errors(formatted_data))

我收到以下验证错误

'rest' is not one of ['test']

Failed validating 'enum' in schema[0]['properties']['app_name']: {'enum': ['test']}

On instance['app_name']: 'rest'

我不确定 schema 本身是无效的还是库 if self 有问题。

我正在使用

python 2.7

jsonschema 2.6.0

好的,架构中似乎有错字。 “True”而不是“true”。

你有:

"uniqueItems": True,

据我所知,它应该是(尽管它仍然可能取决于模式验证器的实现)

"uniqueItems": true,

(参见:http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf section 5 JSON Values and in general https://www.json.org/ - JSON Schema 是一个 JSON 文档并且它符合 JSON 标准)

我已经 运行 通过 .net 在线 JSON 模式验证器 https://www.jsonschemavalidator.net/ 它立即指出了上述模式可能存在的错误。

根据您在 2018 年发表的评论/Nov/16:

As I was passing a value "rest" in app_name. I was expecting an error message "ips" field is required. – Sachin Aryal

完整模式(请注意 "examples" 部分 - 只有最后 2 个示例将根据模式成功验证):

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "anyOf": [
        {
            "properties": {
                "app_name": {"enum": ["test"]}
            },
            "required": ["name"]
        },
        {
            "properties": {
                "app_name": {"enum": ["rest"]}
            },
            "required": ["ips"]
        },
    ],
    "properties": {
        "name": {"type": "string"},
        "ips": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
                "type": "string",
                "pattern": "[^ ]",
                "minLength": 1,
                "maxLength": 50
            }
        },
        "app_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10,
            "enum": [
                "test",
                "rest"
            ]
        }
    },
    "required": [
        "app_name"
    ],
    "examples" : [
      {
        "app_name" : "rest",
      },
      {
        "app_name" : "test",
      },
      {
        "app_name" : "test",
        "ips" : [
         "something1",
         "something2"
        ]
      },
      {
        "app_name" : "rest",
        "name" : "qwerty"
      },
      {
        "app_name" : "test",
        "name" : "qwerty"
      },
      {
        "app_name" : "rest",
        "ips" : [
          "something1",
          "something2"
        ]
      }
    ]
}

您能否更正架构中的项目并使用您的工具进行尝试并让我们知道结果?

最重要的是:

如果您通过验证 JSON 对象,例如:

{
  "app_name" : "rest",
  "name" : "qwerty"
},

针对您的架构,其中使用了 "oneOf" - 验证器 will/should 运行 对象针对 所有 架构 "oneOf" 数组以确保它与提供的模式之一完全匹配。因此 "oneOf/0/" 模式的错误是有效的 - "app_name" : "rest" 不针对定义的枚举进行验证。验证器不知道您通过提供特定的 JSON 来针对模式进行验证是什么意思,所以如果 "allOf" (逻辑异或)条件不满足,我预计所有模式都会出错 JSON 是 运行 反对 "oneOf" 数组(即使这些对你来说似乎是误报)。

如果缺少某些错误消息,您可能需要考虑检查 with/reporting 以 lib 作者您的具体情况。

希望对您有所帮助。

更新

看来您是另一个追逐有意义的错误的人 ;-) 是的,这在使用逻辑运算符时可能会很痛苦。

对于像上面这样的简单情况,您可以使用 draft-07 if-then-else 方法,但是有一个警告 - 请参阅 REMARK。

首先是架构(注意我是如何用两个 "if-then" 替换 "anyOf" 的):

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "if": {
      "properties": {
        "app_name": {"enum": ["test"]}
      },      
    },
    "then" : { "required": ["name"] },
    "if" :  {
      "properties": {
        "app_name": {"enum": ["rest"]}
      },       
    },
    "then" : { "required": ["ips"]},
    "properties": {
        "name": {"type": "string"},
        "ips": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
                "type": "string",
                "pattern": "[^ ]",
                "minLength": 1,
                "maxLength": 50
            }
        },
        "app_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10,
            "enum": [
                "test",
                "rest"
            ]
        }
    },
    "required": [
        "app_name"
    ],
    "examples" : [
      {
        "app_name" : "rest",
      },
      {
        "app_name" : "test",
      },
      {
        "app_name" : "test",
        "ips" : [
         "something1",
         "something2"
        ]
      },
      {
        "app_name" : "rest",
        "name" : "qwerty"
      },
      {
        "app_name" : "test",
        "name" : "qwerty"
      },
      {
        "app_name" : "rest",
        "ips" : [
          "something1",
          "something2"
        ]
      }
    ]
}

备注

模式验证器 jsonschema.net 倾向于在简单情况下提供准确的 if-then-else 错误,当 "then" 和 "else" 中的模式不包含嵌套 "if-then" 并且包含单个 statement/schema 表达式。但是,每当结构化更复杂的情况时,您可能会 运行 进入一般错误消息,例如: JSON 不匹配来自 'then'. 的架构或JSON 与来自 'else'. 的架构不匹配,没有其他详细信息(您需要自行检查 python 输出)。您可以通过适当地塑造依赖关系或子模式来在某种程度上解决它,但是对于非常复杂的模式,如果您需要详细的错误消息,您可能会面临验证器实现错误消息的限制。另请参阅此处的替代模式 2 作为示例:(重点是以某种方式构建模式,if-then-else 在单个关键字模式上失败,其余模式逻辑位于其他关键字下)

话虽如此,您可以始终使用您的工具检查该方法,并在必要时向您最喜欢的库作者提交一份报告,报告有关失败的 if-then-else 模式的错误消息详细信息。

替代"dependencies"

您的案例的另一种选择是使用 draft-06 中的 "dependencies" 关键字,反转初始逻辑和形状 "definitions" 节点,因此它直接导致独特的错误:

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "ips": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
                "type": "string",
                "pattern": "[^ ]",
                "minLength": 1,
                "maxLength": 50
            }
        },
        "app_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10,
            "enum": [
                "test",
                "rest"
            ]
        }
    },
    "required": [
        "app_name"
    ],
    "dependencies" : {
     "ips" : {
        "properties": {
        "app_name": {"$ref":"#/definitions/allowed-app_name-value/rest"}
      },
     },
     "name" : {
      "properties": {
        "app_name": {"$ref":"#/definitions/allowed-app_name-value/test"}
      }, 
     }   
    },
    "definitions" : {
      "allowed-app_name-value" : {
        "test" : {
          "enum": ["test"]
        },
        "rest" : {
          "enum": ["rest"]
        }
      }
    },
    "examples" : [
      {
        "app_name" : "rest",
      },
      {
        "app_name" : "test",
      },
      {
        "app_name" : "test",
        "ips" : [
         "something1",
         "something2"
        ]
      },
      {
        "app_name" : "rest",
        "name" : "qwerty"
      },
      {
        "app_name" : "test",
        "name" : "qwerty"
      },
      {
        "app_name" : "rest",
        "ips" : [
          "something1",
          "something2"
        ]
      }
    ]
}

但它仍然是一种命名解决方法,旨在以人类可读的方式识别确切的错误。例如,jsonschema .net 将为您提供 JSON 行号和消息,如下所示:https://www.newtonsoft.com/jsonschema/help/html/JTokenIsValidWithValidationErrors.htm

每个工具都有自己的错误消息传递方法。请查看 github 上的 JSON 架构团队,因为有一些工作正在为 JSON 下一个草案的架构验证统一输出。

每当以编程方式分析错误时,您可能需要注意错误索引(模式通常嵌套在模式中)是否出现,错误发生在哪一行等。