A comprehensive dataclass instance creation library that enables bidirectional conversion between dictionaries and dataclass instances.
—
High-performance functionality for converting dataclass instances back to dictionaries and other data structures. The serialization system provides up to 10x performance improvement over Python's standard asdict() function with support for custom serializers and naming policies.
Main factory class for creating and caching serializers that convert dataclass instances to dictionaries. The factory automatically detects types and creates appropriate serializers with caching for optimal performance.
class SerializerFactory:
def __init__(
self,
trim_trailing_underscore: bool = True,
debug_path: bool = False,
type_serializers: Dict[Type, Serializer] = None,
name_styles: Dict[Type, NameStyle] = None,
):
"""
Create a serializer factory with configuration options.
Args:
trim_trailing_underscore: Remove trailing underscores from field names
in output dictionaries (e.g., 'id_' field becomes 'id' key)
debug_path: Reserved for future use (not implemented in serializers)
type_serializers: Custom serializer functions for specific types
name_styles: Naming style mappings per dataclass type
"""
def get_serializer(self, cls: Any) -> Serializer:
"""
Get or create a serializer for the specified class.
Args:
cls: The class type to create serializer for
Returns:
Serializer function that converts instances of cls to dictionaries
"""Legacy function for use with Python's standard asdict(). Still provided for compatibility but not recommended for new code as it will be removed in future versions.
def dict_factory(
trim_trailing_underscore: bool = True,
skip_none: bool = False,
skip_internal: bool = False,
type_serializers: Dict[type, Callable] = None
):
"""
Create a dict factory function for use with dataclasses.asdict().
Args:
trim_trailing_underscore: Remove trailing underscores from field names
skip_none: Skip fields with None values
skip_internal: Skip fields starting with underscore
type_serializers: Custom serializers for specific types
Returns:
Dict factory function for use with asdict()
"""from dataclasses import dataclass
from dataclass_factory import SerializerFactory
@dataclass
class Product:
name: str
price: float
in_stock: bool = True
serializer_factory = SerializerFactory()
serializer = serializer_factory.get_serializer(Product)
product = Product("Laptop", 999.99, False)
data = serializer(product)
# Result: {"name": "Laptop", "price": 999.99, "in_stock": False}from dataclasses import dataclass
from typing import List, Optional
from dataclass_factory import SerializerFactory
@dataclass
class Address:
street: str
city: str
country: str = "USA"
@dataclass
class Person:
name: str
age: int
addresses: List[Address]
phone: Optional[str] = None
serializer_factory = SerializerFactory()
serializer = serializer_factory.get_serializer(Person)
person = Person(
name="John Doe",
age=30,
addresses=[
Address("123 Main St", "Anytown"),
Address("456 Oak Ave", "Another City", "Canada")
],
phone="+1-555-0123"
)
data = serializer(person)
# Result: {
# "name": "John Doe",
# "age": 30,
# "addresses": [
# {"street": "123 Main St", "city": "Anytown", "country": "USA"},
# {"street": "456 Oak Ave", "city": "Another City", "country": "Canada"}
# ],
# "phone": "+1-555-0123"
# }from dataclasses import dataclass
from datetime import datetime
from dataclass_factory import SerializerFactory
@dataclass
class Event:
name: str
start_time: datetime
duration_minutes: int
# Create serializer with custom datetime formatting
serializer_factory = SerializerFactory(
type_serializers={datetime: lambda dt: dt.isoformat()}
)
serializer = serializer_factory.get_serializer(Event)
event = Event(
name="Meeting",
start_time=datetime(2023, 12, 25, 10, 0, 0),
duration_minutes=60
)
data = serializer(event)
# Result: {
# "name": "Meeting",
# "start_time": "2023-12-25T10:00:00",
# "duration_minutes": 60
# }from dataclasses import dataclass
from dataclass_factory import SerializerFactory, NameStyle
@dataclass
class ApiResponse:
user_name: str
last_login: str
is_active: bool
# Serialize to camelCase
serializer_factory = SerializerFactory(
name_styles={ApiResponse: NameStyle.camel_lower}
)
serializer = serializer_factory.get_serializer(ApiResponse)
response = ApiResponse(
user_name="johndoe",
last_login="2023-12-25",
is_active=True
)
camel_case_data = serializer(response)
# Result: {
# "userName": "johndoe",
# "lastLogin": "2023-12-25",
# "isActive": True
# }from dataclasses import dataclass
from dataclass_factory import SerializerFactory
@dataclass
class DataWithKeywords:
class_: str # 'class' is a Python keyword
type_: str # 'type' is a Python builtin
id_: int # Common pattern to avoid 'id' builtin
serializer_factory = SerializerFactory(trim_trailing_underscore=True)
serializer = serializer_factory.get_serializer(DataWithKeywords)
data_obj = DataWithKeywords("MyClass", "string", 123)
result = serializer(data_obj)
# Result: {"class": "MyClass", "type": "string", "id": 123}
# Without trimming (trim_trailing_underscore=False)
serializer_no_trim = SerializerFactory(trim_trailing_underscore=False)
serializer_no_trim_func = serializer_no_trim.get_serializer(DataWithKeywords)
result_no_trim = serializer_no_trim_func(data_obj)
# Result: {"class_": "MyClass", "type_": "string", "id_": 123}from dataclasses import dataclass, asdict
from enum import Enum
from dataclass_factory import dict_factory
class Status(Enum):
ACTIVE = "active"
INACTIVE = "inactive"
@dataclass
class User:
name: str
status: Status
id_: int
user = User("John", Status.ACTIVE, 123)
# Using custom dict factory with asdict
factory = dict_factory(
trim_trailing_underscore=True,
skip_none=True
)
result = asdict(user, dict_factory=factory)
# Result: {"name": "John", "status": "active", "id": 123}from typing import Callable, Any
Serializer = Callable[[Any], Any]SerializerFactory provides significant performance improvements over Python's standard asdict():
dataclasses.asdict()For best performance:
Install with Tessl CLI
npx tessl i tessl/pypi-dataclass-factory