Python Cerberus - One is required if another one does not exist

Viewed 121

What I want to achieve:

>>> from cerberus import Validator
>>> schema = {"x": {"type": "integer", "required": False}, "y": {"type": "integer", "required": False}}
>>> v = Validator(schema)
>>> v.validate({"x": 5})
True
>>> v.validate({"y": 6})
True
>>> v.validate({"x": 5, "y": 6})
True
>>> v.validate({})
False

I have checked all the document but still don't know how to achieve this result. How should I define the schema?

1 Answers

The only viable solution is to use Validator() multiple times.

from cerberus import Validator

def composite_validator(document):
    REQUIRED_INTEGER = {"type": 'integer', "required": True}
    OPTIONAL_INTEGER = {"type": 'integer', "required": False}

    schemas = [
        {"x": REQUIRED_INTEGER, "y": OPTIONAL_INTEGER},
        {"x": OPTIONAL_INTEGER, "y": REQUIRED_INTEGER},
    ]
    common_schema = {"z1": REQUIRED_INTEGER, "z2": OPTIONAL_INTEGER, "z3": REQUIRED_INTEGER}
    for s in schemas:
        s.update(common_schema)

    validator = Validator()
    return any(validator(document, s) for s in schemas)

Test results:

for case in [
        {"x": 5, "z1": 0, "z3": -1},
        {"y": 6, "z1": 0, "z3": -1},
        {"x": 5, "y": 6, "z1": 0, "z3": -1},
        {"z1": 0, "z3": -1}]:
    print(case)
    print(composite_validator(case))
#{'x': 5, 'z1': 0, 'z3': -1}
#True
#{'y': 6, 'z1': 0, 'z3': -1}
#True
#{'x': 5, 'y': 6, 'z1': 0, 'z3': -1}
#True
#{'z1': 0, 'z3': -1}
#False
Related