将 oneOf 嵌套在 allOf 中未按预期工作(python jsonschema)
Nesting oneOf inside allOf not working as expected (python jsonschema)
好的,我确定这个 json 架构有问题,但我似乎无法解决这个问题。
我不会 post 实际代码,而是一个重现问题的最小示例。
这是我之前使用的,效果很好:
person = {
'type': 'object',
'properties': {
'name': {
'type': 'string'
}
'auth_token': {
'type': 'string',
},
'username': {
'type': 'string'
},
'password': {
'type': 'string'
}
},
'oneOf': [
{
'required': ['auth_token']
},
{
'required': ['username', 'password']
}
],
'required': ['name']
}
这里的想法是您始终需要提供此人的姓名,然后是身份验证令牌或用户名和密码对。正如我上面所说,此验证工作正常,因为我们已经参数化测试发送无效 JSON 的所有可能组合并评估生成的错误消息,并且这些测试通过。
但是后来出现了一个新的需求,我需要添加第二个互斥的必填字段对,我是这样做的:
person = {
'type': 'object',
'properties': {
'name': {
'type': 'string'
}
'auth_token': {
'type': 'string',
},
'username': {
'type': 'string'
},
'password': {
'type': 'string'
},
'project_id': {
'type': 'number'
},
'contract_date_from': {
'type': 'string'
}
'contract_date_to': {
'type': 'string'
}
},
'allOf': [
{
'oneOf': [
{
'required': ['auth_token']
},
{
'required': ['username', 'password']
}
]
},
{
'oneOf': [
{
'required': ['project_id']
},
{
'required': ['contract_date_from', 'contract_date_to']
}
]
}
],
'required': ['name']
}
但是现在第二次验证总是失败,不管json提供的是有效还是无效。我收到的错误消息是:
{'name': 'John Doe', 'auth_token': '9d9a324b-26de-4ac3-85eb-05566e4a7204', 'username': None, 'password': None, 'project_id': 2785, 'contract_date_from': None, 'contract_date_to': None} is valid under each of {'required': ['contract_date_from', 'contract_date_to']}, {'required': ['project_id']}
无论我在这三个字段中发送什么值(即项目 ID、合同日期和合同日期),它都会失败并出现相同的错误。我试过将所有三个留空,完成所有三个,以及它们之间的所有排列,但错误保持不变。
我一直在阅读 json 架构的文档,但我似乎无法理解此示例的内容。我正在考虑为此尝试不同的方法,但我真的很想了解为什么这不起作用。感谢您的帮助!
{'name': 'John Doe', 'auth_token': '9d9a324b-26de-4ac3-85eb-05566e4a7204', 'username': None, 'password': None, 'project_id': 2785, 'contract_date_from': None, 'contract_date_to': None} is valid under each of {'required': ['contract_date_from', 'contract_date_to']}, {'required': ['project_id']}
更仔细地阅读错误消息:您请求提供 project_id,或者提供 contract_date_from 和 contract_date_to,但您提供了所有这三个。在 属性 中提供空值仍然提供 属性。错误消息令人困惑,但无论如何您都会失败验证,因为 null 不是字符串。你的评估者只是 运行 allOf->anyOfs 首先,所以这是第一个返回的错误。不过,您仍然应该会遇到类型冲突错误(如果没有,那就是错误:评估者需要提供所有错误,而不仅仅是第一个错误。)
您可以通过将“类型”检查添加到“必需”关键字旁边,以牺牲简洁性为代价来改善错误。这将确保 oneOf 关键字产生失败而不是成功,并可能使错误消息更加明显。
好的,我确定这个 json 架构有问题,但我似乎无法解决这个问题。
我不会 post 实际代码,而是一个重现问题的最小示例。
这是我之前使用的,效果很好:
person = {
'type': 'object',
'properties': {
'name': {
'type': 'string'
}
'auth_token': {
'type': 'string',
},
'username': {
'type': 'string'
},
'password': {
'type': 'string'
}
},
'oneOf': [
{
'required': ['auth_token']
},
{
'required': ['username', 'password']
}
],
'required': ['name']
}
这里的想法是您始终需要提供此人的姓名,然后是身份验证令牌或用户名和密码对。正如我上面所说,此验证工作正常,因为我们已经参数化测试发送无效 JSON 的所有可能组合并评估生成的错误消息,并且这些测试通过。
但是后来出现了一个新的需求,我需要添加第二个互斥的必填字段对,我是这样做的:
person = {
'type': 'object',
'properties': {
'name': {
'type': 'string'
}
'auth_token': {
'type': 'string',
},
'username': {
'type': 'string'
},
'password': {
'type': 'string'
},
'project_id': {
'type': 'number'
},
'contract_date_from': {
'type': 'string'
}
'contract_date_to': {
'type': 'string'
}
},
'allOf': [
{
'oneOf': [
{
'required': ['auth_token']
},
{
'required': ['username', 'password']
}
]
},
{
'oneOf': [
{
'required': ['project_id']
},
{
'required': ['contract_date_from', 'contract_date_to']
}
]
}
],
'required': ['name']
}
但是现在第二次验证总是失败,不管json提供的是有效还是无效。我收到的错误消息是:
{'name': 'John Doe', 'auth_token': '9d9a324b-26de-4ac3-85eb-05566e4a7204', 'username': None, 'password': None, 'project_id': 2785, 'contract_date_from': None, 'contract_date_to': None} is valid under each of {'required': ['contract_date_from', 'contract_date_to']}, {'required': ['project_id']}
无论我在这三个字段中发送什么值(即项目 ID、合同日期和合同日期),它都会失败并出现相同的错误。我试过将所有三个留空,完成所有三个,以及它们之间的所有排列,但错误保持不变。
我一直在阅读 json 架构的文档,但我似乎无法理解此示例的内容。我正在考虑为此尝试不同的方法,但我真的很想了解为什么这不起作用。感谢您的帮助!
{'name': 'John Doe', 'auth_token': '9d9a324b-26de-4ac3-85eb-05566e4a7204', 'username': None, 'password': None, 'project_id': 2785, 'contract_date_from': None, 'contract_date_to': None} is valid under each of {'required': ['contract_date_from', 'contract_date_to']}, {'required': ['project_id']}
更仔细地阅读错误消息:您请求提供 project_id,或者提供 contract_date_from 和 contract_date_to,但您提供了所有这三个。在 属性 中提供空值仍然提供 属性。错误消息令人困惑,但无论如何您都会失败验证,因为 null 不是字符串。你的评估者只是 运行 allOf->anyOfs 首先,所以这是第一个返回的错误。不过,您仍然应该会遇到类型冲突错误(如果没有,那就是错误:评估者需要提供所有错误,而不仅仅是第一个错误。)
您可以通过将“类型”检查添加到“必需”关键字旁边,以牺牲简洁性为代价来改善错误。这将确保 oneOf 关键字产生失败而不是成功,并可能使错误消息更加明显。