Validation for Python dictionaries.
zodify validates configuration and script inputs using ordinary Python types. It is written in pure Python with zero required runtime dependencies.
Documentation | Choosing a validator | PyPI | Changelog
pip install zodifySupports Python 3.10–3.13. The project is in alpha. These examples describe 0.8.0, published and verified September 9, 2026. See the compatibility contract for supported behavior and the path to 1.0.
from zodify import validate
schema = {"port": int, "debug": bool}
validate(schema, {"port": 8080, "debug": False})
# {'port': 8080, 'debug': False}
validate(schema, {"port": "8080", "debug": False})
# ValueError: port: expected int, got strA dictionary schema returns a new dictionary. Types are strict by default:
"8080" is a string, so it fails an int check. Failures raise ValueError
with a path to the field. Extra keys are rejected.
| Use cases for zodify | Reasons to consider another approach |
|---|---|
| You already have dictionaries and want reusable checks. | A few direct Python checks already solve the task. |
| You validate configuration, CLI input, or data in scripts. | Your framework already provides the validation you need. |
| Zero required runtime dependencies matter. | You need a broader annotation vocabulary, model features, or specialized serialization. |
Pydantic supports both models and TypeAdapter for ordinary types, including
dictionaries. Use a dedicated JSON Schema implementation when a JSON Schema
document is your validation language. The
comparison guide explains the tradeoffs.
Use nested dictionaries, single-element lists, unions, and optional keys as needed:
from zodify import Optional, validate
schema = {
"db": {"host": str, "port": Optional(int, 5432)},
"tags": [str],
"debug": Optional(bool, False),
}
validate(schema, {"db": {"host": "localhost"}, "tags": ["prod"]})
# {'db': {'host': 'localhost', 'port': 5432}, 'tags': ['prod'], 'debug': False}Conversions are explicit. For string inputs such as configuration values:
validate({"port": int}, {"port": "8080"}, coerce=True)
# {'port': 8080}Schema grammar and conversion rules cover the details.
- Strict types: ordinary validation does not coerce values.
boolandintare distinct. Setcoerce=Trueto opt into the documented conversions. - Unknown keys: rejected by default.
unknown_keys="strip"drops them. - Missing versus null:
Optional(type)permits omission;type | Nonepermits a null value. These are separate choices. - Default ownership: defaults are trusted, without validation or copying. Mutable defaults can be shared between results. Successful validation does not make data deeply immutable.
- Errors: text mode raises
ValueError. Witherror_mode="structured",ValidationErroradds legacy.issuesand canonical.details. - Depth:
max_depth=32counts shaped dictionary traversals, including the root. It does not limit list nesting, input size, or general resource use.
See defaults and ownership and error handling.
For attribute access, declare a supported Schema:
from zodify import Schema, validate
class Config(Schema):
port: int
debug: bool = False
config = validate(Config, {"port": 8080})
print(config.port) # 8080Validate class declarations with validate(Config, data). Direct Config()
instantiation is unsupported. Annotations are limited to the documented subset.
See class schemas and limitations.
| Task | Guide |
|---|---|
| Run your first validation | Getting started |
| Validate application configuration | Configuration guide |
| Validate command-line input | CLI guide |
| Parse and validate a JSON object | JSON input guide |
| Look up options, env parsing, errors, or JSON export limits | Full API reference |
| Run complete examples | Example scripts |
env() reads one variable; load_env() parses an env file without changing the
process environment. In schema mode, load_env() defaults to coercion and unknown-key
stripping, unlike ordinary validation. Env file loading, canonical details, and
conservative JSON input/export require 0.8.0; the quickstart also works with 0.6.0.
Read the contributor guide for local checks and the release procedure for publication. Report problems in GitHub Issues.
Benchmark methodology documents the measured workloads and comparison limits. The roadmap distinguishes released features from plans. Compilation remains outside the public API. The implementation issue tracks direction.
Copyright 2026 Jun Young Sohn.