# serialization ## model_dump convert a model to a dict. control what's included: ```python class Track(BaseModel): id: int title: str artist_did: str internal_score: float track.model_dump() # all fields track.model_dump(exclude={"internal_score"}) # omit internal fields track.model_dump(include={"id", "title"}) # only these track.model_dump(mode="json") # json-compatible types (datetimes → strings) ``` `mode="json"` is important — without it, you get python objects (datetime, Decimal). with it, everything is JSON-serializable. ## model_dump_json / model_validate_json skip the dict intermediary for performance: ```python # serialize directly to JSON string json_str = track.model_dump_json() # deserialize directly from JSON string track = Track.model_validate_json(json_str) ``` faster than `json.dumps(track.model_dump())` because pydantic uses rust-based serialization internally. useful for Redis caching: ```python await redis.set(cache_key, response.model_dump_json(), ex=300) cached = await redis.get(cache_key) if cached: return AlbumResponse.model_validate_json(cached) ``` ## computed fields fields derived from other fields, included in serialization but not accepted as input: ```python from pydantic import BaseModel, computed_field class Album(BaseModel): tracks: list[Track] @computed_field @property def track_count(self) -> int: return len(self.tracks) @computed_field @property def total_duration(self) -> float: return sum(t.duration for t in self.tracks) ``` shows up in `model_dump()` and JSON output. not stored, always recomputed. ## TypeAdapter for ad-hoc validation validate data without defining a full model: ```python from pydantic import TypeAdapter int_adapter = TypeAdapter(int) int_adapter.validate_python("42") # → 42 int_adapter.validate_python("abc") # → ValidationError # useful for parsing env var fragments StatusCode = Annotated[int, Field(ge=100, le=599)] code_adapter = TypeAdapter(StatusCode) code_adapter.validate_python(429) # → 429 code_adapter.validate_python(999) # → ValidationError ``` also handles complex types: `TypeAdapter(list[int])`, `TypeAdapter(dict[str, float])`. ## response models in FastAPI FastAPI uses pydantic models for automatic request validation and response serialization: ```python class PlaylistResponse(BaseModel): id: str name: str track_count: int created_at: str @router.get("/playlists/{id}", response_model=PlaylistResponse) async def get_playlist(id: str) -> PlaylistResponse: ... ``` the `response_model` strips any extra fields from the return value — useful when your internal object has more data than the API should expose. sources: - [pydantic docs: serialization](https://docs.pydantic.dev/latest/concepts/serialization/) - [pydantic docs: type adapter](https://docs.pydantic.dev/latest/concepts/type_adapter/)