Serialization¶
Every alchemiq model can serialize itself to a plain dictionary, convert to a
validated Pydantic object, or generate a reusable Pydantic schema class.
All three paths respect include/exclude filtering and handle special
column types such as Maybe[T] and Password automatically.
to_dict - serialize to a dictionary¶
data = instance.to_dict()
Mode¶
The mode keyword controls how values are coerced:
Mode |
Behaviour |
|---|---|
|
Native Python types: |
|
JSON-safe scalars: |
# Python-native values
d = user.to_dict() # datetime stays a datetime object
# JSON-ready values
d = user.to_dict(mode="json") # datetime -> "2025-03-01T12:00:00+00:00"
Field selection¶
# Include only specific fields
d = user.to_dict(include={"id", "email"})
# Exclude specific fields
d = user.to_dict(exclude={"created_at", "updated_at"})
Password fields are omitted unless explicitly listed in include.
Inlining relations¶
Pass eagerly-loaded relationship names via relations to inline them
recursively:
d = order.to_dict(relations=("items",))
# {"id": 1, "status": "paid", "items": [{"id": 10, ...}, ...]}
Maybe[T] unwrapping¶
Columns declared as Maybe[T] always hold either Some(value) or
Nothing on the model instance. Both to_dict modes unwrap the
container automatically:
In
"python"mode:Some(v)->v,Nothing->NoneIn
"json"mode:Some(v)-> coerced scalar,Nothing->None
from alchemiq.types import Maybe, Some, Nothing
class Profile(Model):
id: PK[int]
bio: Maybe[str]
profile.bio = Some("Hello")
profile.to_dict() # {"id": 1, "bio": "Hello"}
profile.bio = Nothing
profile.to_dict() # {"id": 1, "bio": None}
The unwrapping happens in both modes, so you never see raw Some/Nothing
objects in the output.
to_schema - generate a Pydantic schema class¶
to_schema() is a classmethod that builds and caches a pydantic.BaseModel
subclass whose fields mirror the model’s columns:
UserSchema = User.to_schema()
UserPublicSchema = User.to_schema(exclude={"password_hash"})
The result is a standard Pydantic class. Use it for FastAPI request/response typing, manual validation, or JSON serialisation:
schema = User.to_schema(include={"id", "name", "email"})
validated = schema.model_validate({"id": 1, "name": "Ada", "email": "ada@example.com"})
The schema is memoised per (include, exclude) pair on the model class, so
repeated calls with the same arguments return the same class object.
Password fields are excluded unless explicitly whitelisted in include.
to_pydantic - convert an instance to a schema object¶
to_pydantic() calls to_schema() and to_dict(mode="python")
internally, then validates the dict through the schema:
dto = user.to_pydantic()
# dto is a pydantic.BaseModel instance - fully validated
print(dto.model_dump())
It is equivalent to:
User.to_schema().model_validate(user.to_dict(mode="python"))
Use to_pydantic() when you need a typed, validated DTO to pass between
layers, and to_dict(mode="json") when you need a JSON-serialisable dict
directly.