在allOf中嵌套oneOf未按预期工作(python jsonschema)



好吧,我确信这个jsonschema有问题,但我似乎无法理解这个问题。

我不打算发布实际的代码,而是一个简单的例子来重现这个问题。

这是我以前做的,效果很好:

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’:无,‘password’:无、‘project_id’:2785、‘contract_date_from’:无’、‘contact_date_to’:无}在以下各项下均有效

仔细阅读错误消息:您请求提供project_id、OR contract_date_from和contract_date _to,但您提供了这三个选项。在属性中提供null值仍然是在提供属性。错误消息令人困惑,但由于null不是字符串,您无论如何都无法通过验证。您的评估者只是在运行allOf->anyOfs优先,所以这是最先出现的错误。不过,你仍然应该得到类型冲突错误(如果你没有,那就是一个错误:评估人员需要提供所有错误,而不仅仅是第一个错误。(

您可以通过添加";类型";检查居住在";"必需";关键字。这将确保oneOf关键字产生失败而不是成功,并可能使错误消息更加明显。