I try to validate a jsonschema that defines a circle either with a radius
or a diameter
or neither and then just sets a default radius. This is my schema:
{
"properties": {
"position": {},
"radius": {
{ "type": "number" }
},
"diameter": {
{ "type": "number" }
}
},
"oneOf": [
{
"required": ["radius"]
},
{
"required": ["diameter"]
},
{
"properties": {
"radius": {
"default": 16
}
}
}
],
"additionalProperties": false
}
This is the validator, that sets the default value (as described at JSON schema FAQ):
from jsonschema import Draft7Validator, validators
def extend_with_default(validator_class):
validate_properties = validator_class.VALIDATORS['properties']
def set_defaults(validator, properties, instance, schema):
for property, subschema in properties.items():
if 'default' in subschema:
instance.setdefault(property, subschema['default'])
for error in validate_properties(
validator, properties, instance, schema,
):
yield error
return validators.extend(
validator_class, {'properties' : set_defaults},
)
Validator = extend_with_default(Draft7Validator)
This validator sets the default value before I validate the schema, so I can only set the radius or neither, but setting the diameter will always raise an error. If I change this to validate first and set default values later (which I would rather not, but ok), then it sets the default radius despite the required diameter already existing.
Is there some way to implement this without hard-coding it by setting the default-radius in python?
The validator does not need to be changed. This is a possible soluation:
{
"properties": {
"position": {},
"radius": {
{ "type": "number" }
},
"diameter": {
{ "type": "number" }
}
},
"if": {
"not": {
"anyOf": [
{
"required": ["radius"]
},
{
"required": ["diameter"]
}
]
}
},
"then": {
"properties": {
"radius": {
"default": 16
}
}
},
"oneOf": [
{
"required": ["radius"]
},
{
"required": ["diameter"]
}
],
"additionalProperties": false
}
if
will be only true, if neither radius or diameter are set. Only then will the default radius be set. Afterwards oneOf
checks, if only one of the parameters is set at the same time.