CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-dataclass-factory

A comprehensive dataclass instance creation library that enables bidirectional conversion between dictionaries and dataclass instances.

Pending
Overview
Eval results
Files

serialization.mddocs/

Data Serialization

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.

Capabilities

SerializerFactory

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 Dict Factory

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()
    """

Usage Examples

Basic Dataclass Serialization

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}

Complex Nested Types

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"
# }

Custom Type Serializers

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
# }

Naming Policies

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
# }

Trailing Underscore Handling

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}

Using Legacy Dict Factory

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}

Types

from typing import Callable, Any

Serializer = Callable[[Any], Any]

Performance

SerializerFactory provides significant performance improvements over Python's standard asdict():

  • Up to 10x faster than dataclasses.asdict()
  • Caching: Serializers are created once and cached for reuse
  • Type optimization: Direct field access without reflection overhead
  • Optimized nested handling: Efficient processing of complex nested structures

For best performance:

  1. Create SerializerFactory once at application startup
  2. Reuse serializers for the same types
  3. Use type_serializers for expensive custom type conversions

Install with Tessl CLI

npx tessl i tessl/pypi-dataclass-factory

docs

index.md

naming.md

parsing.md

serialization.md

tile.json