问题描述
我尝试验证使用 radius
或 diameter
或两者都不定义圆的 jsonschema,然后仅设置默认半径。这是我的架构:
{
"properties": {
"position": {},"radius": {
{ "type": "number" }
},"diameter": {
{ "type": "number" }
}
},"oneOf": [
{
"required": ["radius"]
},{
"required": ["diameter"]
},{
"properties": {
"radius": {
"default": 16
}
}
}
],"additionalProperties": false
}
这是设置默认值的验证器(如 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,schema,):
yield error
return validators.extend(
validator_class,{'properties' : set_defaults},)
Validator = extend_with_default(Draft7Validator)
此验证器在我验证架构之前设置默认值,因此我只能设置半径或两者都不设置,但是设置直径总是会引发错误。 如果我将其更改为首先验证并稍后设置默认值(我宁愿不这样做,但可以),那么它会设置默认半径,尽管所需的直径已经存在。
有没有办法通过在 python 中设置默认半径来实现这一点,而无需对其进行硬编码?
解决方法
验证器不需要更改。这是一个可能的解决方案:
{
"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
仅在半径或直径均未设置的情况下为真。只有这样才会设置默认半径。然后 oneOf
检查是否只有一个参数同时被设置。