CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyserde

Yet another serialization library on top of dataclasses

Pending
Overview
Eval results
Files

field-configuration.mddocs/

Field Configuration and Customization

Advanced field-level configuration for customizing serialization behavior, field renaming, conditional serialization, custom serializers, and field flattening. The field function provides fine-grained control over how individual fields are processed.

Capabilities

Field Definition

The field function extends dataclasses.field with serialization-specific parameters.

def field(
    default=...,
    default_factory=...,
    init: bool = True,
    repr: bool = True,
    hash: bool | None = None,
    compare: bool = True,
    metadata: dict | None = None,
    rename: str | None = None,
    alias: list[str] | None = None,
    serializer: Callable | None = None,
    deserializer: Callable | None = None,
    flatten: bool = False,
    skip: bool = False,
    skip_if: Callable | None = None,
    skip_if_false: bool = False,
    skip_if_default: bool = False,
) -> Any:
    """
    Define field with serialization parameters.
    
    Standard dataclass parameters:
    - default: Default value for the field
    - default_factory: Function to generate default value
    - init: Include field in __init__
    - repr: Include field in __repr__
    - hash: Include field in __hash__
    - compare: Include field in comparison operations
    - metadata: Additional metadata dictionary
    
    pyserde-specific parameters:
    - rename: Alternative name for serialization
    - alias: List of alternative names for deserialization
    - serializer: Custom serializer function for this field
    - deserializer: Custom deserializer function for this field
    - flatten: Flatten nested object fields into parent
    - skip: Skip field during serialization/deserialization
    - skip_if: Function to conditionally skip field
    - skip_if_false: Skip field if value is falsy
    - skip_if_default: Skip field if value equals default
    
    Returns:
    Field descriptor with custom serialization behavior
    """

Custom Serializers and Deserializers

Functions for registering global custom serialization logic.

def add_serializer(serializer: ClassSerializer) -> None:
    """
    Register custom global serializer.
    
    Parameters:
    - serializer: ClassSerializer instance to register globally
    """

def add_deserializer(deserializer: ClassDeserializer) -> None:
    """
    Register custom global deserializer.
    
    Parameters:
    - deserializer: ClassDeserializer instance to register globally
    """

def default_serializer(_cls: type[Any], obj: Any) -> Any:
    """
    Marker function to tell serde to use the default serializer.
    Used when custom serializer is specified at the class level but 
    you want to override a field with the default serializer.
    
    Parameters:
    - _cls: Class type (not used)
    - obj: Object to serialize
    
    Returns:
    Serialized representation using default logic
    """

def default_deserializer(_cls: type[Any], obj: Any) -> Any:
    """
    Marker function to tell serde to use the default deserializer.
    Used when custom deserializer is specified at the class level but
    you want to override a field with the default deserializer.
    
    Parameters:
    - _cls: Class type to deserialize to
    - obj: Object to deserialize
    
    Returns:
    Deserialized object using default logic
    """

Class-Level Serializers

Protocol classes for implementing custom class-level serialization behavior.

class ClassSerializer(Protocol):
    """Protocol for custom class serializers."""
    
    def serialize(self, obj: Any) -> Any:
        """
        Serialize object to intermediate representation.
        
        Parameters:
        - obj: Object to serialize
        
        Returns:
        Serialized representation
        """

class ClassDeserializer(Protocol):
    """Protocol for custom class deserializers."""
    
    def deserialize(self, cls: type, data: Any) -> Any:
        """
        Deserialize data to object instance.
        
        Parameters:
        - cls: Target class type
        - data: Data to deserialize
        
        Returns:
        Deserialized object instance
        """

Usage Examples

Field Renaming

from serde import serde, field

@serde
class User:
    username: str = field(rename="user_name")
    email_address: str = field(rename="email")
    full_name: str = field(rename="name")

user = User("alice", "alice@example.com", "Alice Smith")
data = to_dict(user)
# {'user_name': 'alice', 'email': 'alice@example.com', 'name': 'Alice Smith'}

Conditional Field Skipping

from serde import serde, field

@serde
class Config:
    host: str
    port: int
    debug: bool = field(skip_if_false=True)
    secret_key: str | None = field(skip_if=lambda x: x is None)
    default_timeout: int = field(default=30, skip_if_default=True)

config = Config("localhost", 8080, False, None, 30)
data = to_dict(config)
# {'host': 'localhost', 'port': 8080}  # debug, secret_key, and default_timeout skipped

Custom Field Serializers

from serde import serde, field
from datetime import datetime

def serialize_timestamp(dt: datetime) -> int:
    return int(dt.timestamp())

def deserialize_timestamp(cls, timestamp: int) -> datetime:
    return datetime.fromtimestamp(timestamp)

@serde
class Event:
    name: str
    created_at: datetime = field(
        serializer=serialize_timestamp,
        deserializer=deserialize_timestamp
    )

event = Event("Meeting", datetime(2023, 12, 25, 10, 30))
data = to_dict(event)
# {'name': 'Meeting', 'created_at': 1703502600}

Field Flattening

from serde import serde, field

@serde
class Address:
    street: str
    city: str
    country: str

@serde
class Person:
    name: str
    age: int
    address: Address = field(flatten=True)

person = Person("Alice", 30, Address("123 Main St", "Boston", "USA"))
data = to_dict(person)
# {
#     'name': 'Alice', 
#     'age': 30,
#     'street': '123 Main St',
#     'city': 'Boston', 
#     'country': 'USA'
# }

Global Custom Serializers

from serde import serde, add_serializer, add_deserializer
from decimal import Decimal

def decimal_serializer(obj: Decimal) -> str:
    return str(obj)

def decimal_deserializer(cls, data: str) -> Decimal:
    return Decimal(data)

# Register global serializers
add_serializer(Decimal, decimal_serializer)
add_deserializer(Decimal, decimal_deserializer)

@serde
class Product:
    name: str
    price: Decimal

product = Product("Widget", Decimal("19.99"))
data = to_dict(product)
# {'name': 'Widget', 'price': '19.99'}

Class-Level Custom Serializers

from serde import serde, ClassSerializer, ClassDeserializer

class TimestampSerializer:
    def serialize(self, obj):
        result = {}
        for field_name, field_value in obj.__dict__.items():
            if isinstance(field_value, datetime):
                result[field_name] = int(field_value.timestamp())
            else:
                result[field_name] = field_value
        return result

class TimestampDeserializer:
    def deserialize(self, cls, data):
        kwargs = {}
        for field_name, field_value in data.items():
            field_type = cls.__annotations__.get(field_name)
            if field_type == datetime:
                kwargs[field_name] = datetime.fromtimestamp(field_value)
            else:
                kwargs[field_name] = field_value
        return cls(**kwargs)

@serde(
    class_serializer=TimestampSerializer(),
    class_deserializer=TimestampDeserializer()
)
class LogEntry:
    message: str
    timestamp: datetime
    level: str

Install with Tessl CLI

npx tessl i tessl/pypi-pyserde

docs

core-serialization.md

field-configuration.md

format-modules.md

index.md

type-system.md

union-handling.md

tile.json