0
# Data Serialization
1
2
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.
3
4
## Capabilities
5
6
### SerializerFactory
7
8
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.
9
10
```python { .api }
11
class SerializerFactory:
12
def __init__(
13
self,
14
trim_trailing_underscore: bool = True,
15
debug_path: bool = False,
16
type_serializers: Dict[Type, Serializer] = None,
17
name_styles: Dict[Type, NameStyle] = None,
18
):
19
"""
20
Create a serializer factory with configuration options.
21
22
Args:
23
trim_trailing_underscore: Remove trailing underscores from field names
24
in output dictionaries (e.g., 'id_' field becomes 'id' key)
25
debug_path: Reserved for future use (not implemented in serializers)
26
type_serializers: Custom serializer functions for specific types
27
name_styles: Naming style mappings per dataclass type
28
"""
29
30
def get_serializer(self, cls: Any) -> Serializer:
31
"""
32
Get or create a serializer for the specified class.
33
34
Args:
35
cls: The class type to create serializer for
36
37
Returns:
38
Serializer function that converts instances of cls to dictionaries
39
"""
40
```
41
42
### Legacy Dict Factory
43
44
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.
45
46
```python { .api }
47
def dict_factory(
48
trim_trailing_underscore: bool = True,
49
skip_none: bool = False,
50
skip_internal: bool = False,
51
type_serializers: Dict[type, Callable] = None
52
):
53
"""
54
Create a dict factory function for use with dataclasses.asdict().
55
56
Args:
57
trim_trailing_underscore: Remove trailing underscores from field names
58
skip_none: Skip fields with None values
59
skip_internal: Skip fields starting with underscore
60
type_serializers: Custom serializers for specific types
61
62
Returns:
63
Dict factory function for use with asdict()
64
"""
65
```
66
67
### Usage Examples
68
69
#### Basic Dataclass Serialization
70
71
```python
72
from dataclasses import dataclass
73
from dataclass_factory import SerializerFactory
74
75
@dataclass
76
class Product:
77
name: str
78
price: float
79
in_stock: bool = True
80
81
serializer_factory = SerializerFactory()
82
serializer = serializer_factory.get_serializer(Product)
83
84
product = Product("Laptop", 999.99, False)
85
data = serializer(product)
86
# Result: {"name": "Laptop", "price": 999.99, "in_stock": False}
87
```
88
89
#### Complex Nested Types
90
91
```python
92
from dataclasses import dataclass
93
from typing import List, Optional
94
from dataclass_factory import SerializerFactory
95
96
@dataclass
97
class Address:
98
street: str
99
city: str
100
country: str = "USA"
101
102
@dataclass
103
class Person:
104
name: str
105
age: int
106
addresses: List[Address]
107
phone: Optional[str] = None
108
109
serializer_factory = SerializerFactory()
110
serializer = serializer_factory.get_serializer(Person)
111
112
person = Person(
113
name="John Doe",
114
age=30,
115
addresses=[
116
Address("123 Main St", "Anytown"),
117
Address("456 Oak Ave", "Another City", "Canada")
118
],
119
phone="+1-555-0123"
120
)
121
122
data = serializer(person)
123
# Result: {
124
# "name": "John Doe",
125
# "age": 30,
126
# "addresses": [
127
# {"street": "123 Main St", "city": "Anytown", "country": "USA"},
128
# {"street": "456 Oak Ave", "city": "Another City", "country": "Canada"}
129
# ],
130
# "phone": "+1-555-0123"
131
# }
132
```
133
134
#### Custom Type Serializers
135
136
```python
137
from dataclasses import dataclass
138
from datetime import datetime
139
from dataclass_factory import SerializerFactory
140
141
@dataclass
142
class Event:
143
name: str
144
start_time: datetime
145
duration_minutes: int
146
147
# Create serializer with custom datetime formatting
148
serializer_factory = SerializerFactory(
149
type_serializers={datetime: lambda dt: dt.isoformat()}
150
)
151
serializer = serializer_factory.get_serializer(Event)
152
153
event = Event(
154
name="Meeting",
155
start_time=datetime(2023, 12, 25, 10, 0, 0),
156
duration_minutes=60
157
)
158
159
data = serializer(event)
160
# Result: {
161
# "name": "Meeting",
162
# "start_time": "2023-12-25T10:00:00",
163
# "duration_minutes": 60
164
# }
165
```
166
167
#### Naming Policies
168
169
```python
170
from dataclasses import dataclass
171
from dataclass_factory import SerializerFactory, NameStyle
172
173
@dataclass
174
class ApiResponse:
175
user_name: str
176
last_login: str
177
is_active: bool
178
179
# Serialize to camelCase
180
serializer_factory = SerializerFactory(
181
name_styles={ApiResponse: NameStyle.camel_lower}
182
)
183
serializer = serializer_factory.get_serializer(ApiResponse)
184
185
response = ApiResponse(
186
user_name="johndoe",
187
last_login="2023-12-25",
188
is_active=True
189
)
190
191
camel_case_data = serializer(response)
192
# Result: {
193
# "userName": "johndoe",
194
# "lastLogin": "2023-12-25",
195
# "isActive": True
196
# }
197
```
198
199
#### Trailing Underscore Handling
200
201
```python
202
from dataclasses import dataclass
203
from dataclass_factory import SerializerFactory
204
205
@dataclass
206
class DataWithKeywords:
207
class_: str # 'class' is a Python keyword
208
type_: str # 'type' is a Python builtin
209
id_: int # Common pattern to avoid 'id' builtin
210
211
serializer_factory = SerializerFactory(trim_trailing_underscore=True)
212
serializer = serializer_factory.get_serializer(DataWithKeywords)
213
214
data_obj = DataWithKeywords("MyClass", "string", 123)
215
result = serializer(data_obj)
216
# Result: {"class": "MyClass", "type": "string", "id": 123}
217
218
# Without trimming (trim_trailing_underscore=False)
219
serializer_no_trim = SerializerFactory(trim_trailing_underscore=False)
220
serializer_no_trim_func = serializer_no_trim.get_serializer(DataWithKeywords)
221
result_no_trim = serializer_no_trim_func(data_obj)
222
# Result: {"class_": "MyClass", "type_": "string", "id_": 123}
223
```
224
225
#### Using Legacy Dict Factory
226
227
```python
228
from dataclasses import dataclass, asdict
229
from enum import Enum
230
from dataclass_factory import dict_factory
231
232
class Status(Enum):
233
ACTIVE = "active"
234
INACTIVE = "inactive"
235
236
@dataclass
237
class User:
238
name: str
239
status: Status
240
id_: int
241
242
user = User("John", Status.ACTIVE, 123)
243
244
# Using custom dict factory with asdict
245
factory = dict_factory(
246
trim_trailing_underscore=True,
247
skip_none=True
248
)
249
result = asdict(user, dict_factory=factory)
250
# Result: {"name": "John", "status": "active", "id": 123}
251
```
252
253
## Types
254
255
```python { .api }
256
from typing import Callable, Any
257
258
Serializer = Callable[[Any], Any]
259
```
260
261
## Performance
262
263
SerializerFactory provides significant performance improvements over Python's standard `asdict()`:
264
265
- **Up to 10x faster** than `dataclasses.asdict()`
266
- **Caching**: Serializers are created once and cached for reuse
267
- **Type optimization**: Direct field access without reflection overhead
268
- **Optimized nested handling**: Efficient processing of complex nested structures
269
270
For best performance:
271
1. Create SerializerFactory once at application startup
272
2. Reuse serializers for the same types
273
3. Use type_serializers for expensive custom type conversions