How to Validate Data with a Simple Dict-Based Rules Helper in Python
Validates a dictionary against a set of callable rules, printing pass/fail per field and returning an overall boolean.
Python code
34 linesimport json
from pathlib import Path
from typing import Any, Callable
def validate_data(
data: dict[str, Any],
rules: dict[str, Callable[[Any], bool]],
path: Path | None = None,
) -> bool:
"""Validate a dict against a set of simple rules."""
all_valid = True
for field, validator in rules.items():
value = data.get(field)
is_valid = validator(value)
all_valid = all_valid and is_valid
print(f"{field}: {value!r} -> {'PASS' if is_valid else 'FAIL'}")
return all_valid
if __name__ == "__main__":
sample = {"name": "Alice", "age": 30, "email": "alice@example.com"}
rules = {
"name": lambda v: isinstance(v, str) and len(v) > 0,
"age": lambda v: isinstance(v, int) and v >= 18,
"email": lambda v: "@" in v if v else False,
}
result = validate_data(sample, rules)
print(f"Overall: {'VALID' if result else 'INVALID'}")
# Try a failing case
bad = {"name": "", "age": 12, "email": None}
print("\nSecond check:")
validate_data(bad, rules)
Output
name: 'Alice' -> PASS
age: 30 -> PASS
email: 'alice@example.com' -> PASS
Overall: VALID
Second check:
name: '' -> FAIL
age: 12 -> FAIL
email: None -> FAIL
How it works
The validate_data function takes a dictionary and a rules dictionary where each key maps to a callable that returns a boolean. It uses the .get() method to safely access fields, tolerating missing keys (which become None). The all_valid flag accumulates the AND of each check, and the function prints a clear PASS/FAIL line for each field. This pattern is simple, readable, and easily extendable—you can replace the lambda validators with named functions or type-checked callables without changing the core design.
Common mistakes
- Using `data[field]` instead of `.get()`, which raises KeyError on missing keys
- Forgetting that `all_valid = all_valid and is_valid` is needed to accumulate (not just per-field)
- Writing validators that assume the value exists; handle `None` explicitly in lambdas
- Not using `if __name__ == "__main__"` guard, so the demo runs on import
Variations
- Use a list of (field, validator) tuples instead of a dict to preserve order and allow duplicate fields
- Raise a custom exception listing failed fields instead of printing to stdout
Real-world use cases
- Validating user input from a web form before saving to a database.
- Checking configuration dictionaries loaded from environment variables or YAML files.
- Sanity-checking API response payloads before processing them in a pipeline.
Sponsored
More from Modern tooling
- Build a Recipe Runner Mock in Python easy
- Build a Textual TUI App Skeleton in Python easy
- Configure ruff linter rules in pyproject.toml with Python easy
- Data Conversion Helper Functions in Python easy
- How to Bind and Mock structlog Context in Python medium
- How to Build a Chainable Filter Helper in Python easy
Keep learning
Related tutorials and quizzes for this topic.