Using cerberus 1.0, you can implement this using oneof
rule in its agglutinating form as in this documentation example. With this, you can validate against different schemas of which exactly one must validate:
The downside is that you may need an additional level on you dict, like price
below:
First schema, freight and price:
>>> schema_1 = {'freight_id': {'type': 'integer', 'required': True},
... 'price': {'type': 'integer', 'required': True}}
Second schema, tender and price:
>>> schema_2 = {'tender_id': {'type': 'integer', 'required': True},
... 'price': {'type': 'integer', 'required': True}}
Third schema, freight, tender and price:
>>> schema_3 = {'tender_id': {'type': 'integer', 'required': True},
... 'freight_id': {'type': 'integer', 'required': True},
... 'price': {'type': 'integer', 'required': True}}
Putting these together:
>>> from cerberus import Validator
>>>
>>> price_validator = Validator(
... {'price': {'type': 'dict',
... 'oneof_schema': [schema_1, schema_2, schema_3]}})
The results:
>>> price_validator.validate({"price": {"freight_id": 1, "price" : 12000}})
True
>>> price_validator.validate({"price": {"tender_id": 2, "price" : 12000}})
True
>>> price_validator.validate(
... {"price": {"freight_id": 1, "tender_id": 2, "price": 1200}})
True
>>> price_validator.validate({"price": {"freight_id": 1, "tender_id": 2}})
False
>>> price_validator.validate({"price": {"price" : 12000}})
False