Serializing Dataclasses
As I am working with dataclass and wanting to return the values in a simplified serialized format that AWS Lambda and other brittle response wrappers can handle. Lambda is able to handle the base class of dict[str, str] as serializable, I wrote this helper method to perform recursive serialization.
It works reasonable well as I don't have any complicated types on purpose with deep nesting. The painful cases are dates, times, enums, and exceptions and this handles those without issue.
Note
Do not make a case of Iterator over list, set in my experience this will give you unpredictable representations as str properties will be decoded into arrays of characters.
import dataclasses
from datetime import datetime, timedelta
from enum import Enum
from typing import Any
from uuid import UUID
def serialize_dataclass(obj: Any) -> dict[str, Any]:
if dataclasses.is_dataclass(obj):
return serialize_dataclass(dataclasses.asdict(obj)) # type: ignore[arg-type]
if isinstance(obj, dict):
for key, value in obj.items():
if isinstance(value, dict):
obj[key] = serialize_dataclass(value)
continue
if isinstance(value, datetime):
obj[key] = value.isoformat()
continue
if isinstance(value, timedelta):
obj[key] = value.__str__()
continue
if isinstance(value, Exception):
obj[key] = value.__repr__()
continue
# expecting that enum base class off of str like so class TheEnum(str, Enum): order is important
# or use the StrEnum enum base class after 3.11
if isinstance(value, Enum):
obj[key] = value.value
continue
if isinstance(value, UUID):
obj[key] = str(value)
continue
if isinstance(value, list | set):
obj[key] = [serialize_dataclass(z) for z in value]
return obj