Skip to content

Repository files navigation

zodify

zodify

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

Install

pip install zodify

Supports 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.

Quick Start

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 str

A 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.

Choosing a validator

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.

Schemas

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.

Validation behavior

  • Strict types: ordinary validation does not coerce values. bool and int are distinct. Set coerce=True to opt into the documented conversions.
  • Unknown keys: rejected by default. unknown_keys="strip" drops them.
  • Missing versus null: Optional(type) permits omission; type | None permits 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. With error_mode="structured", ValidationError adds legacy .issues and canonical .details.
  • Depth: max_depth=32 counts 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.

Optional class syntax

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)  # 8080

Validate class declarations with validate(Config, data). Direct Config() instantiation is unsupported. Annotations are limited to the documented subset. See class schemas and limitations.

Guides and reference

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.

Project and contributions

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.

License

MIT

Copyright 2026 Jun Young Sohn.

About

Validation for Python dictionaries with no required runtime dependencies.

Topics

Resources

Contributing

Stars

9 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages