0
# Field Configuration and Customization
1
2
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.
3
4
## Capabilities
5
6
### Field Definition
7
8
The field function extends dataclasses.field with serialization-specific parameters.
9
10
```python { .api }
11
def field(
12
default=...,
13
default_factory=...,
14
init: bool = True,
15
repr: bool = True,
16
hash: bool | None = None,
17
compare: bool = True,
18
metadata: dict | None = None,
19
rename: str | None = None,
20
alias: list[str] | None = None,
21
serializer: Callable | None = None,
22
deserializer: Callable | None = None,
23
flatten: bool = False,
24
skip: bool = False,
25
skip_if: Callable | None = None,
26
skip_if_false: bool = False,
27
skip_if_default: bool = False,
28
) -> Any:
29
"""
30
Define field with serialization parameters.
31
32
Standard dataclass parameters:
33
- default: Default value for the field
34
- default_factory: Function to generate default value
35
- init: Include field in __init__
36
- repr: Include field in __repr__
37
- hash: Include field in __hash__
38
- compare: Include field in comparison operations
39
- metadata: Additional metadata dictionary
40
41
pyserde-specific parameters:
42
- rename: Alternative name for serialization
43
- alias: List of alternative names for deserialization
44
- serializer: Custom serializer function for this field
45
- deserializer: Custom deserializer function for this field
46
- flatten: Flatten nested object fields into parent
47
- skip: Skip field during serialization/deserialization
48
- skip_if: Function to conditionally skip field
49
- skip_if_false: Skip field if value is falsy
50
- skip_if_default: Skip field if value equals default
51
52
Returns:
53
Field descriptor with custom serialization behavior
54
"""
55
```
56
57
### Custom Serializers and Deserializers
58
59
Functions for registering global custom serialization logic.
60
61
```python { .api }
62
def add_serializer(serializer: ClassSerializer) -> None:
63
"""
64
Register custom global serializer.
65
66
Parameters:
67
- serializer: ClassSerializer instance to register globally
68
"""
69
70
def add_deserializer(deserializer: ClassDeserializer) -> None:
71
"""
72
Register custom global deserializer.
73
74
Parameters:
75
- deserializer: ClassDeserializer instance to register globally
76
"""
77
78
def default_serializer(_cls: type[Any], obj: Any) -> Any:
79
"""
80
Marker function to tell serde to use the default serializer.
81
Used when custom serializer is specified at the class level but
82
you want to override a field with the default serializer.
83
84
Parameters:
85
- _cls: Class type (not used)
86
- obj: Object to serialize
87
88
Returns:
89
Serialized representation using default logic
90
"""
91
92
def default_deserializer(_cls: type[Any], obj: Any) -> Any:
93
"""
94
Marker function to tell serde to use the default deserializer.
95
Used when custom deserializer is specified at the class level but
96
you want to override a field with the default deserializer.
97
98
Parameters:
99
- _cls: Class type to deserialize to
100
- obj: Object to deserialize
101
102
Returns:
103
Deserialized object using default logic
104
"""
105
```
106
107
### Class-Level Serializers
108
109
Protocol classes for implementing custom class-level serialization behavior.
110
111
```python { .api }
112
class ClassSerializer(Protocol):
113
"""Protocol for custom class serializers."""
114
115
def serialize(self, obj: Any) -> Any:
116
"""
117
Serialize object to intermediate representation.
118
119
Parameters:
120
- obj: Object to serialize
121
122
Returns:
123
Serialized representation
124
"""
125
126
class ClassDeserializer(Protocol):
127
"""Protocol for custom class deserializers."""
128
129
def deserialize(self, cls: type, data: Any) -> Any:
130
"""
131
Deserialize data to object instance.
132
133
Parameters:
134
- cls: Target class type
135
- data: Data to deserialize
136
137
Returns:
138
Deserialized object instance
139
"""
140
```
141
142
## Usage Examples
143
144
### Field Renaming
145
146
```python
147
from serde import serde, field
148
149
@serde
150
class User:
151
username: str = field(rename="user_name")
152
email_address: str = field(rename="email")
153
full_name: str = field(rename="name")
154
155
user = User("alice", "alice@example.com", "Alice Smith")
156
data = to_dict(user)
157
# {'user_name': 'alice', 'email': 'alice@example.com', 'name': 'Alice Smith'}
158
```
159
160
### Conditional Field Skipping
161
162
```python
163
from serde import serde, field
164
165
@serde
166
class Config:
167
host: str
168
port: int
169
debug: bool = field(skip_if_false=True)
170
secret_key: str | None = field(skip_if=lambda x: x is None)
171
default_timeout: int = field(default=30, skip_if_default=True)
172
173
config = Config("localhost", 8080, False, None, 30)
174
data = to_dict(config)
175
# {'host': 'localhost', 'port': 8080} # debug, secret_key, and default_timeout skipped
176
```
177
178
### Custom Field Serializers
179
180
```python
181
from serde import serde, field
182
from datetime import datetime
183
184
def serialize_timestamp(dt: datetime) -> int:
185
return int(dt.timestamp())
186
187
def deserialize_timestamp(cls, timestamp: int) -> datetime:
188
return datetime.fromtimestamp(timestamp)
189
190
@serde
191
class Event:
192
name: str
193
created_at: datetime = field(
194
serializer=serialize_timestamp,
195
deserializer=deserialize_timestamp
196
)
197
198
event = Event("Meeting", datetime(2023, 12, 25, 10, 30))
199
data = to_dict(event)
200
# {'name': 'Meeting', 'created_at': 1703502600}
201
```
202
203
### Field Flattening
204
205
```python
206
from serde import serde, field
207
208
@serde
209
class Address:
210
street: str
211
city: str
212
country: str
213
214
@serde
215
class Person:
216
name: str
217
age: int
218
address: Address = field(flatten=True)
219
220
person = Person("Alice", 30, Address("123 Main St", "Boston", "USA"))
221
data = to_dict(person)
222
# {
223
# 'name': 'Alice',
224
# 'age': 30,
225
# 'street': '123 Main St',
226
# 'city': 'Boston',
227
# 'country': 'USA'
228
# }
229
```
230
231
### Global Custom Serializers
232
233
```python
234
from serde import serde, add_serializer, add_deserializer
235
from decimal import Decimal
236
237
def decimal_serializer(obj: Decimal) -> str:
238
return str(obj)
239
240
def decimal_deserializer(cls, data: str) -> Decimal:
241
return Decimal(data)
242
243
# Register global serializers
244
add_serializer(Decimal, decimal_serializer)
245
add_deserializer(Decimal, decimal_deserializer)
246
247
@serde
248
class Product:
249
name: str
250
price: Decimal
251
252
product = Product("Widget", Decimal("19.99"))
253
data = to_dict(product)
254
# {'name': 'Widget', 'price': '19.99'}
255
```
256
257
### Class-Level Custom Serializers
258
259
```python
260
from serde import serde, ClassSerializer, ClassDeserializer
261
262
class TimestampSerializer:
263
def serialize(self, obj):
264
result = {}
265
for field_name, field_value in obj.__dict__.items():
266
if isinstance(field_value, datetime):
267
result[field_name] = int(field_value.timestamp())
268
else:
269
result[field_name] = field_value
270
return result
271
272
class TimestampDeserializer:
273
def deserialize(self, cls, data):
274
kwargs = {}
275
for field_name, field_value in data.items():
276
field_type = cls.__annotations__.get(field_name)
277
if field_type == datetime:
278
kwargs[field_name] = datetime.fromtimestamp(field_value)
279
else:
280
kwargs[field_name] = field_value
281
return cls(**kwargs)
282
283
@serde(
284
class_serializer=TimestampSerializer(),
285
class_deserializer=TimestampDeserializer()
286
)
287
class LogEntry:
288
message: str
289
timestamp: datetime
290
level: str
291
```