Types and Composition

Types, Constraints and Composition Keywords

type names one of null, boolean, object, array, number, string or integer. Constraints such as enum, minimum and pattern narrow it, and composition combines subschemas with allOf, anyOf, oneOf, not and if/then/else, which BookNest's events need: only order_placed carries customer_id and total.

Conditional rules for order events, and a multipleOf trapPython
from jsonschema import Draft202012Validator
event = Draft202012Validator({
    "required": ["type", "order_id"],
    "if": {"properties": {"type": {"const": "order_placed"}}},
    "then": {"required": ["customer_id", "total"]},
    "else": {"not": {"anyOf": [{"required": ["customer_id"]}, {"required": ["total"]}]}}})
for e in [{"type": "order_placed", "order_id": 5},
          {"type": "order_paid", "order_id": 2, "total": 106.8}]:
    print(e["type"], [f"{'/'.join(map(str, x.schema_path))}" for x in event.iter_errors(e)])
cents = Draft202012Validator({"multipleOf": 0.01})
print({x: cents.is_valid(x) for x in (106.8, 19.99, 0.07)})
Output
order_placed ['then/required', 'then/required']
order_paid ['else/not']
{106.8: True, 19.99: False, 0.07: False}

The last line is Numbers and Precision's float problem again: 19.99 / 0.01 is not exactly an integer in binary, so a valid price fails multipleOf: 0.01. Constrain money as integer cents or as a pattern-checked string instead.