python
41 lines · 6 steps
JSON round-tripping with Python dataclasses
A nested dataclass serializes itself to JSON and rebuilds from it, handling datetimes and nested objects along the way.
Explained by
highlit
1import json
2from dataclasses import dataclass, field, asdict
3from datetime import datetime
4from typing import Any
5
6
7@dataclass
8class Address:
9 street: str
10 city: str
11 zip_code: str
12
13
14@dataclass
15class User:
16 id: int
17 name: str
18 email: str
19 address: Address
20 tags: list[str] = field(default_factory=list)
21 created_at: datetime = field(default_factory=datetime.utcnow)
22
23 def to_json(self, **kwargs: Any) -> str:
24 def default(obj: Any) -> Any:
25 if isinstance(obj, datetime):
26 return obj.isoformat()
27 raise TypeError(f"Cannot serialize {type(obj).__name__}")
28
29 return json.dumps(asdict(self), default=default, **kwargs)
30
31 @classmethod
32 def from_json(cls, raw: str) -> "User":
33 data = json.loads(raw)
34 return cls(
35 id=data["id"],
36 name=data["name"],
37 email=data["email"],
38 address=Address(**data["address"]),
39 tags=data.get("tags", []),
40 created_at=datetime.fromisoformat(data["created_at"]),
41 )
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1asdict recursively flattens nested dataclasses into plain dicts ready for json.dumps.
- 2json.dumps accepts a default callback to teach it how to serialize types it doesn't natively understand, like datetime.
- 3Reconstruction is manual because JSON has no type info, so nested objects and datetimes must be rebuilt field by field.
Related explainers
python
import secrets from fastapi import Depends, FastAPI, HTTPException, Security, status from fastapi.security import APIKeyHeader
API key authentication as a FastAPI dependency
authentication
dependency-injection
api-keys
Intermediate
8 steps
python
import hashlib from collections import defaultdict from pathlib import Path
Finding duplicate files by size then hash
hashing
file-io
deduplication
Intermediate
7 steps
python
from flask import Flask, request, g, jsonify from flask_babel import Babel, gettext as _, format_datetime from datetime import datetime
Per-request localization in Flask with Babel
i18n
content-negotiation
request-lifecycle
Intermediate
8 steps
python
from django.core.cache import cache from django.core.cache.utils import make_template_fragment_key from django.db.models.signals import post_save, post_delete from django.dispatch import receiver
Busting template fragment caches in Django
caching
signals
cache-invalidation
Intermediate
4 steps
python
from datetime import datetime, timezone _INTERVALS = ( ("year", 60 * 60 * 24 * 365),
Building a human-friendly time_ago helper
datetime
timezones
formatting
Intermediate
5 steps
python
import time import threading from flask import Flask, request, jsonify, g
A token-bucket rate limiter in Flask
rate-limiting
token-bucket
middleware
Intermediate
7 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/json-round-tripping-with-python-dataclasses-explained-python-aa70/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.