Reputation: 11
I am trying to get proper validation error from oneof or anyof pattern. I have json schema with two or more oneof/anyof condition as mentioned below:
json_schema = {
"type": "object",
"properties": {
"comment": {
"description": "Server Pool Policy Qualification Comments",
"type": "string",
"default": ""
},
"name": {
"description": "Server Pool Policy Qualification Name",
"type": "string",
"default": "",
"pattern": "^[\\-\\.:_a-zA-Z0-9]{1,16}$"
},
"qualifications": {
"description": "Qualifications of Server Pool Policy Qualification",
"type": "array",
"items": {
"description": "Qualification of Server Pool Policy Qualification",
"type": "object",
"oneOf": [
{
"properties": {
"type": {
"description": "Qualification Type",
"type": "string",
"enum": [
"adapter"
]
},
"adapter_qualification":{
"description": "Adapter Qualifications - Adapter Type",
"type": "array",
"properties": {
"adapter_type": {
"description": "Adapter Qualifications - Adapter Type",
"type": "string",
"enum": [
"virtualized-scsi-if"
]
},
"adapter_pid": {
"description": "Adapter Qualifications - Adapter PID (RegEx)",
"type": "string",
"default": "",
"pattern": "[ !#$%\\(\\)\\*\\+,\\-\\./:;\\?@\\[\\\\\\]\\^_\\{\\|\\}~a-zA-Z0-9]{0,256}"
},
"adapter_maximum_capacity": {
"description": "Adapter Qualifications - Maximum Capacity",
"type": "string",
"default": "unspecified",
"pattern": "^unspecified$|^[0-9]$|^[0-9][0-9]$|^[0-9][0-9][0-9]$|^[0-9][0-9][0-9][0-9]$|^[0-5][0-9][0-9][0-9][0-9]$|^6[0-4][0-9][0-9][0-9]$|^65[0-4][0-9][0-9]$|^655[0-2][0-9]$|^6553[0-5]$"
}
},
"additionalProperties": False,
"required": [
"type",
"adapter_type"
]
}
}
},
{
"properties": {
"type": {
"description": "Qualification Type",
"type": "string",
"enum": [
"server_pid"
]
},
"server_pid": {
"description": "Server PID Qualifications - Server PID",
"type": "string",
"default": "",
"pattern": "^123$"
}
},
"additionalProperties": False,
"required": [
"type",
"server_pid"
]
}
]
}
}
},
"additionalProperties": False,
"required": [
"name"
]
}
I have data which has additional element first_rack_id but best matches 2nd element from oneof.
data = {
"descr": "description",
"name": "domainGroup",
"qualifications": [
{
"server_pid": "B200M5",
"type": "server_pid",
"first_rack_id": "10"
}
]
}
validator = Draft7Validator(json_schema)
best = best_match(validator.iter_errors(data))
My expectation is that the error message thrown by validation will find 2nd element from oneof and throw error saying additional property is not allowed. but i get match for 1st element as mentioned below:
'server_pid' is not one of ['adapter']
Failed validating 'enum' in schema[0]['properties']['type']:
{'description': 'Qualification Type',
'enum': ['adapter'],
'type': 'string'}
On instance['type']:
'server_pid'
how do i specify validator to best match with property "type" which will match with enum "server_pid" instead of enum "adapter"
Upvotes: 1
Views: 3190
Reputation: 71
Since best_match
need a sort key
to help match errors and the default key is to use most depth errors key, see:
So maybe you can use a less depth key to match the errors.(below function is just a draft test, you can use it as reference)
def match_less_path(error):
return len(error.path)
best = best_match(validator.iter_errors(data), match_less_path)
And I test the output like this:
Additional properties are not allowed ('first_rack_id' was unexpected)
Failed validating 'additionalProperties' in schema[1]:
{'additionalProperties': False,
'properties': {'server_pid': {'default': '',
'description': 'Server PID '
'Qualifications - Server '
'PID',
'pattern': '^123$',
'type': 'string'},
'type': {'description': 'Qualification Type',
'enum': ['server_pid'],
'type': 'string'}},
'required': ['type', 'server_pid']}
On instance:
{'first_rack_id': '10', 'server_pid': 'B200M5', 'type': 'server_pid'}
Upvotes: 0
Reputation: 24439
You can specify which schema to validate against with the if
/then
keywords. It's a bit verbose and can be error prone, but it's the best way to express this sort of thing. Although popular, oneOf
is almost never the right choice.
"allOf": [
{
"if": {
"type": "object",
"properties": {
"type": { "const": "adapter" }
},
"required": ["type"]
},
"then": { "$ref": "#/definitions/adapter" }
},
{
"if": {
"type": "object",
"properties": {
"type": { "const": "server_pid" }
},
"required": ["type"]
},
"then": { "$ref": "#/definitions/server-pid" }
}
],
Upvotes: 2