python - jsonschema验证未按预期返回错误?

标签 python python-2.7 jsonschema

我正在使用此架构,我希望基于值的条件架构。


  如果app_name为“ test”,则应输入属性名称。
  
  如果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']中的“枚举”失败:
      {'枚举':['test']}
  
  在instance ['app_name']上:
      '休息'


我不确定模式本身是否无效,或者如果self是库问题。

我在用


  python 2.7
  
  jsonschema 2.6.0

最佳答案

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

你有:

"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”字段为必填字段。 – Sachin Aryal


完整的架构(请注意“示例”部分-仅最后两个示例将针对架构成功验证):

{
    "$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”数组中的所有架构运行对象,以确保其与提供的架构之一完全匹配。因此,“ oneOf / 0 /”架构的错误是有效的-“ app_name”:“ rest”未针对定义的枚举进行验证。验证程序不知道通过提供特定的JSON来针对架构进行验证的含义,因此,如果不满足“ allOf”(逻辑XOR)条件,则我希望所有架构的错误都在“ oneOf”数组中针对JSON进行(即使这些对您来说都是假阳性)。

如果缺少某些错误消息,您可能要考虑与/向lib作者报告确切的情况。

希望能有所帮助。

更新

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

对于上面的简单情况,您可以使用草案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"
        ]
      }
    ]
}


备注

在简单情况下,当“ then”和“ else”中的模式不包含嵌套的“ if-then”并且由单个语句/模式表达式组成时,模式验证器jsonschema.net倾向于提供准确的if-then-else错误。但是,每当构建更复杂的案例时,您可能会遇到一般错误消息,例如:JSON与“ then”中的架构不匹配。或JSON与“ else”中的架构不匹配。没有其他详细信息(您需要自己检查python输出)。您可以通过适当地调整依赖项或子模式来解决该问题,但是对于非常复杂的架构,如果您追究详细的错误消息,则无论如何您可能会面临验证程序实现错误消息的限制。请在此处另请参阅替代方案2作为示例:https://stackoverflow.com/a/53320222/2811843(整个意义在于以某种方式构造方案,如果if-then-else在单个关键字方案上失败,而方案逻辑的其余部分位于其他关键字下)

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

带有“依赖项”的替代项

针对您的情况的另一种选择是使用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 Schema团队,因为正在为下一个草案进行统一JSON Schema验证的输出方面的工作。

每当以编程方式分析错误时,如果出现错误索引(方案通常嵌套在架构中),您可能要注意它们,错误发生在哪一行等。

关于python - jsonschema验证未按预期返回错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53075861/

相关文章:

python - 不能再在 Windows 上运行 python

java - 如何使用 json-schema-validator 根据超模式验证 JSON

java - 如何在 Java 中验证 JSON 模式?

java - 使用 java - ref 的 JSON 模式验证

python - 如何使用 Django Check Constraint 在数据库级别限制变量?

python - 克隆存储库时如何管理依赖关系?

python - 将字符串中的单词替换为 pandas 数据框中的单词

python - bool() 和 operator.truth() 有什么区别?

python - 如何在 Python 中调用父类(super class)中的子类方法

python - Python 中的 HTML 字符串解码