【问题标题】:jsonschema validation not returning error as expected?jsonschema 验证没有按预期返回错误?
【发布时间】:2018-10-31 03:30:30
【问题描述】:

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

如果 app_name 是“test”,那么属性 name 应该是必需的。

如果 app_name 如果 "rest" 则属性 ips 应该是必需的。

{
    "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' 不是 ['test'] 之一

在架构 [0]['properties']['app_name'] 中验证“枚举”失败: {'enum': ['test']}

在实例上['app_name']: '休息'

我不确定模式本身是否无效,或者如果 self.

我正在使用

python 2.7

jsonschema 2.6.0

【问题讨论】:

  • JSON 架构有效。那个错误是正确的。您希望看到什么错误消息?
  • 当我在 app_name 中传递一个值“rest”时。我期待一个错误消息“ips”字段是必需的。
  • 看起来他们只报告了一个错误,因为这两个 oneOf 条件都失败了。正如其中一个问题所指出的,如果您尝试jsonschemavalidator.net,它会报告这两个错误。 JSON Schema 目前没有定义错误/验证错误报告的标准,因此我的问题是“您希望看到什么?”。我知道这可能不是你想听到的答案!
  • 我不应该,我们(JSON Schema 团队)认识到这是一个问题,正在寻求定义标准错误输出!
  • jsonschemavalidator.net 它报告了两个错误,我希望看到Required properties are missing from object: ips.

标签: python python-2.7 jsonschema


【解决方案1】:

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

你有:

"uniqueItems": True,

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

"uniqueItems": true,

(请参阅:http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf 第 5 节 JSON 值和一般情况下https://www.json.org/ - JSON Schema 是 JSON 文档,它符合 JSON 标准)

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

根据您在 2018 年 11 月 16 日的评论,在更正错字之后,它似乎可以正常工作:

当我在 app_name 中传递一个值“rest”时。我期待一个错误 消息“ips”字段是必需的。 – 萨钦·阿里亚尔

完整的架构(请注意“示例”部分 - 只有最后 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”的架构 - 验证器将/应该针对“oneOf”数组中的 all 架构运行对象,以确保它与提供的架构之一完全匹配。因此,“oneOf/0/”模式的错误是有效的 - "app_name" : "rest" 不会针对定义的枚举进行验证。验证器不知道您提供特定 JSON 以针对模式进行验证是什么意思,因此如果不满足“allOf”(逻辑 XOR)条件,我预计 JSON 在“oneOf”数组中运行的所有模式都会出现错误(即使这些对您来说似乎是误报)。

如果缺少某些错误消息,您可能需要考虑向 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”并且由单个语句/模式表达式组成时。但是,每当构建更复杂的案例时,您可能会遇到一般错误消息,例如:JSON 不匹配来自 'then' 的架构。JSON 不匹配来自 'else' 的架构。 没有额外的细节(你需要自己检查 python 输出)。您可以通过适当地塑造依赖关系或子模式来解决它,但对于非常复杂的模式,如果您在详细的错误消息之后,您可能会面临验证器实现错误消息的限制。另请参阅此处作为示例的替代模式 2:https://stackoverflow.com/a/53320222/2811843(重点是以某种方式构建模式,即 if-then-else 在单个关键字模式上失败,其余模式逻辑位于其他关键字下)

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

“依赖项”的替代方案

您的情况的另一种选择是使用 draft-06 中的“依赖项”关键字,反转初始逻辑并塑造“定义”节点,以便直接导致唯一错误:

{
    "$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 Schema 团队,因为正在为下一个草案统一 JSON Schema 验证的输出。

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

【讨论】:

  • 这不是拼写错误(我使用的是 python 字典),如果我尝试使用 jsonschemavalidator.net ,它会给我预期的错误消息。例如,如果我传递以下数据 { "app_name" : "rest", "name" : "qwerty" } I got this error {'app_name': 'rest', 'name': 'qwerty'} 在 python 中的任何给定模式下都无效。当我使用 jsonschemavalidator.net 尝试此操作时,我收到 3 条错误消息。可能是报错有问题
  • @SachinAryal 预计会有多个错误消息。正如我所提到的,逻辑运算符强制验证器通过 *Of 语句中的所有模式运行(以防 JSON 文档与模式不匹配)。错误消息取决于实现,但通常有一点,lib/tool 逻辑根本不知道您的意思是什么,并提供在所有模式中发现的所有错误,如上所述。我正在使用 if-then-else 更新答案(不是它的粉丝,但对于简单的情况,它可能会起作用 - 请注意 REMARK 部分)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 2017-02-04
  • 1970-01-01
  • 2019-03-15
  • 2013-05-17
相关资源
最近更新 更多