An implementation of JSON Schema validation for Python
—
Comprehensive error reporting system providing detailed validation failure information, error organization utilities, and tools for finding the most relevant errors in complex validation scenarios.
The primary exception raised when JSON Schema validation fails, containing detailed information about the validation failure.
class ValidationError(Exception):
"""
Exception raised when validation fails.
Attributes:
- message: Human-readable error message
- path: Path to the failing instance property
- schema_path: Path to the failing schema property
- context: List of sub-errors for complex validations
- validator: The validator keyword that failed
- validator_value: The schema value for the failed validator
- instance: The instance value that failed validation
- schema: The schema that validation failed against
- parent: Parent error for nested validations
"""
def __init__(self,
message,
validator=None,
path=(),
cause=None,
context=(),
validator_value=None,
instance=None,
schema=None,
schema_path=(),
parent=None,
type_checker=None):
"""
Initialize validation error.
Parameters:
- message: Error description
- validator: Validator keyword that failed
- path: Path to failing instance property
- cause: Underlying exception that caused the error
- context: Sub-errors for complex validations
- validator_value: Schema value for failed validator
- instance: Instance value that failed
- schema: Schema that failed
- schema_path: Path to failing schema property
- parent: Parent error for nested validations
- type_checker: Type checker used during validation
"""
@property
def absolute_path(self):
"""
Absolute path to the failing instance property.
Returns:
- deque: Complete path from root to failing property
"""
@property
def absolute_schema_path(self):
"""
Absolute path to the failing schema property.
Returns:
- deque: Complete path from root to failing schema property
"""
@property
def json_path(self):
"""
JSONPath expression for the failing instance property.
Returns:
- str: JSONPath expression
"""Exception raised when a schema itself is invalid.
class SchemaError(Exception):
"""
Exception raised when a schema is invalid.
Inherits all attributes and methods from ValidationError.
"""Hierarchical organization of validation errors for complex schemas with nested validation rules.
class ErrorTree:
"""
Tree structure for organizing validation errors.
Provides dictionary-like and attribute-like access to errors
organized by the path where they occurred.
"""
def __init__(self, errors=()):
"""
Initialize error tree.
Parameters:
- errors: Iterable of ValidationError objects
"""
@property
def errors(self):
"""
Direct errors at this tree node.
Returns:
- frozenset: Errors that occurred at this exact path
"""
@property
def total_errors(self):
"""
Total number of errors in tree and all subtrees.
Returns:
- int: Total error count
"""
def __getitem__(self, index):
"""
Access subtree by path component.
Parameters:
- index: Path component (string or integer)
Returns:
- ErrorTree: Subtree for the given path component
"""
def __contains__(self, index):
"""
Check if path component has errors.
Parameters:
- index: Path component to check
Returns:
- bool: True if path has errors
"""Utilities for finding the most relevant errors from complex validation results.
def best_match(errors, key=None):
"""
Find the most relevant error from a collection of errors.
Parameters:
- errors: Iterable of ValidationError objects
- key: Function to compute error relevance (optional)
Returns:
- ValidationError: Most relevant error
"""
def by_relevance(weak=WEAK_MATCHES, strong=STRONG_MATCHES):
"""
Create error relevance function for best_match.
Parameters:
- weak: Set of weakly matching validator keywords
- strong: Set of strongly matching validator keywords
Returns:
- function: Relevance function for error comparison
"""
# Pre-configured relevance function
relevance: callable
"""
Pre-configured key function for sorting errors by relevance.
This is a pre-configured instance of by_relevance() that can be used
directly with sorted() or as the key parameter for best_match().
Example:
sorted(validator.iter_errors(instance), key=relevance)
"""Specialized exceptions for specific error conditions.
class UndefinedTypeCheck(Exception):
"""Raised when an undefined type is used in type checking."""
class UnknownType(Exception):
"""Raised when an unknown type name is encountered."""
class FormatError(Exception):
"""Raised when format validation fails."""from jsonschema import Draft202012Validator, ValidationError
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer", "minimum": 0}
},
"required": ["name", "age"]
}
validator = Draft202012Validator(schema)
invalid_data = {"name": 123} # Wrong type for name, missing age
try:
validator.validate(invalid_data)
except ValidationError as e:
print(f"Error: {e.message}")
print(f"Path: {'.'.join(str(p) for p in e.path)}")
print(f"Failed validator: {e.validator}")
print(f"Schema path: {'.'.join(str(p) for p in e.schema_path)}")from jsonschema import Draft202012Validator
validator = Draft202012Validator(schema)
invalid_data = {"name": 123, "age": -5} # Multiple errors
errors = list(validator.iter_errors(invalid_data))
print(f"Found {len(errors)} errors:")
for error in errors:
path = '.'.join(str(p) for p in error.path) if error.path else 'root'
print(f" - {path}: {error.message}")from jsonschema import Draft202012Validator, ErrorTree
schema = {
"type": "object",
"properties": {
"users": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string", "format": "email"}
},
"required": ["name", "email"]
}
}
}
}
validator = Draft202012Validator(schema)
invalid_data = {
"users": [
{"name": "Alice"}, # Missing email
{"email": "invalid-email"} # Missing name, invalid email
]
}
errors = validator.iter_errors(invalid_data)
tree = ErrorTree(errors)
# Access errors by path
if 'users' in tree:
users_tree = tree['users']
if 0 in users_tree:
print("Errors in first user:", users_tree[0].errors)
if 1 in users_tree:
print("Errors in second user:", users_tree[1].errors)
print(f"Total errors: {tree.total_errors}")from jsonschema import Draft202012Validator, best_match
schema = {
"anyOf": [
{"type": "string"},
{"type": "number"},
{"type": "object", "properties": {"name": {"type": "string"}}}
]
}
validator = Draft202012Validator(schema)
invalid_data = {"name": 123} # Object with wrong property type
errors = list(validator.iter_errors(invalid_data))
most_relevant = best_match(errors)
print(f"Most relevant error: {most_relevant.message}")from jsonschema import Draft202012Validator
schema = {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {"type": "string"}
}
}
}
validator = Draft202012Validator(schema)
invalid_data = {"data": ["valid", 123, "also_valid"]}
for error in validator.iter_errors(invalid_data):
print(f"JSONPath: {error.json_path}")
print(f"Error: {error.message}")from jsonschema import Draft202012Validator
schema = {
"oneOf": [
{"type": "string", "minLength": 5},
{"type": "number", "minimum": 10}
]
}
validator = Draft202012Validator(schema)
invalid_data = "hi" # Too short for string, not a number
errors = list(validator.iter_errors(invalid_data))
for error in errors:
print(f"Main error: {error.message}")
if error.context:
print("Context errors:")
for ctx_error in error.context:
print(f" - {ctx_error.message}")Install with Tessl CLI
npx tessl i tessl/pypi-jsonschema