This schema is the sample orders' contract, closed with additionalProperties: false at both levels:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/booknest/order.schema.json",
"type": "object", "additionalProperties": false,
"required": ["order_id", "customer_id", "order_ts", "channel", "status", "currency",
"items", "coupon", "discount", "total"],
"properties": {
"order_id": {"type": "integer", "minimum": 1},
"customer_id": {"type": "integer", "minimum": 1},
"order_ts": {"type": "string", "format": "date-time"},
"channel": {"enum": ["ios", "android", "web"]},
"status": {"enum": ["pending", "paid", "shipped", "delivered", "cancelled", "returned"]},
"currency": {"const": "USD"},
"items": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/item"}},
"coupon": {"type": ["string", "null"], "pattern": "^[A-Z]+[0-9]{2}$"},
"discount": {"$ref": "#/$defs/money"}, "total": {"$ref": "#/$defs/money"}
},
"$defs": {
"money": {"type": "number", "minimum": 0},
"item": {"type": "object", "additionalProperties": false,
"required": ["book_id", "qty", "unit_price"],
"properties": {"book_id": {"type": "integer", "minimum": 1, "maximum": 6},
"qty": {"type": "integer", "minimum": 1, "maximum": 3},
"unit_price": {"$ref": "#/$defs/money"}}}
}
}jsonschema 4.26.0 (github.com/python-jsonschema/jsonschema (https://github.com/python-jsonschema/jsonschema 4,988 ), pip 21,050 install "jsonschema[format]") implements drafts 3 to 2020-12; a FormatChecker makes format an assertion. On three corrupted orders in bad-orders.jsonl, the script reports every error with its location:
import json, sys
from jsonschema import Draft202012Validator, FormatChecker
schema = json.load(open("order.schema.json", encoding="utf-8"))
v = Draft202012Validator(schema, format_checker=FormatChecker())
for n, line in enumerate(open(sys.argv[1], encoding="utf-8"), start=1):
for err in v.iter_errors(json.loads(line)):
print(f"line {n} {err.json_path}: {err.message}")Output
line 1 $.items[0].qty: 0 is less than the minimum of 1
line 1 $.items[1].book_id: 7 is greater than the maximum of 6
line 2 $.order_ts: '2025-02-30T10:00:00Z' is not a 'date-time'
line 2 $.channel: 'fax' is not one of ['ios', 'android', 'web']
line 3 $: Additional properties are not allowed ('gift' was unexpected)
line 3 $: 'coupon' is a required property
line 3 $.total: '21.30' is not of type 'number'All 100,000 sample orders pass, at about 1,000 to 1,500 a second on this shared 4-CPU host; fastjsonschema compiles schemas to Python code and ran 30 times faster, but supports only drafts 04 to 07.