0
# Serialization and Configuration
1
2
Computed fields, serialization customization, and model configuration options for controlling validation and serialization behavior.
3
4
## Capabilities
5
6
### Computed Fields
7
8
Create fields that are computed from other fields or model state, useful for derived values and dynamic properties.
9
10
```python { .api }
11
def computed_field(*, alias=None, alias_priority=None, title=None, description=None,
12
examples=None, exclude=None, discriminator=None, json_schema_extra=None,
13
frozen=None, validate_default=None, repr=True, return_type=PydanticUndefined):
14
"""
15
Decorator for computed field properties.
16
17
Args:
18
alias: Alias for the field name
19
alias_priority (int): Priority for alias resolution
20
title (str): Human-readable title
21
description (str): Field description
22
examples: Example values
23
exclude: Whether to exclude from serialization
24
discriminator: Discriminator for union types
25
json_schema_extra: Extra JSON schema properties
26
frozen (bool): Whether field is frozen after initialization
27
validate_default (bool): Validate default values
28
repr (bool): Include in repr output
29
return_type: Return type annotation
30
31
Returns:
32
Decorator function
33
"""
34
35
@computed_field
36
@property
37
def computed_property(self) -> ReturnType:
38
"""
39
Template for computed field property.
40
41
Returns:
42
Computed value
43
"""
44
```
45
46
### Model Configuration
47
48
Configuration options that control model behavior, validation, and serialization.
49
50
```python { .api }
51
class ConfigDict(TypedDict, total=False):
52
"""
53
Configuration dictionary for pydantic models.
54
55
Can be used as model_config class attribute.
56
"""
57
58
# Validation configuration
59
strict: bool # Enable strict validation mode
60
extra: str # Handle extra fields ('ignore', 'allow', 'forbid')
61
frozen: bool # Make model immutable after creation
62
populate_by_name: bool # Allow field population by field name and alias
63
use_enum_values: bool # Use enum values instead of enum instances
64
validate_assignment: bool # Validate field assignments after creation
65
arbitrary_types_allowed: bool # Allow arbitrary types in fields
66
from_attributes: bool # Allow model creation from object attributes
67
68
# Serialization configuration
69
ser_json_timedelta: str # How to serialize timedelta ('iso8601', 'float')
70
ser_json_bytes: str # How to serialize bytes ('utf8', 'base64')
71
ser_json_inf_nan: str # How to serialize inf/nan ('null', 'constants')
72
hide_input_in_errors: bool # Hide input data in validation errors
73
74
# String handling
75
str_to_lower: bool # Convert strings to lowercase
76
str_to_upper: bool # Convert strings to uppercase
77
str_strip_whitespace: bool # Strip whitespace from strings
78
79
# JSON schema configuration
80
title: str # Schema title
81
json_schema_extra: dict # Extra JSON schema properties
82
json_encoders: dict # Custom JSON encoders (deprecated)
83
84
# Deprecated/legacy options
85
validate_default: bool # Validate default values
86
defer_build: bool # Defer model building
87
```
88
89
### Serialization Decorators
90
91
Decorators for customizing field and model serialization behavior.
92
93
```python { .api }
94
def field_serializer(*fields, mode='wrap', when_used='json-unless-none', check_fields=None):
95
"""
96
Decorator for custom field serialization.
97
98
Args:
99
*fields (str): Field names to apply serializer to
100
mode (str): Serialization mode ('wrap', 'plain', 'before', 'after')
101
when_used (str): When to use serializer ('json', 'json-unless-none', 'always')
102
check_fields (bool): Whether to check if fields exist
103
104
Returns:
105
Decorator function
106
"""
107
108
def model_serializer(mode='wrap', when_used='json-unless-none'):
109
"""
110
Decorator for custom model serialization.
111
112
Args:
113
mode (str): Serialization mode ('wrap', 'plain')
114
when_used (str): When to use serializer ('json', 'json-unless-none', 'always')
115
116
Returns:
117
Decorator function
118
"""
119
120
class PlainSerializer:
121
"""
122
Serializer that completely replaces default serialization.
123
"""
124
125
def __init__(self, func, *, return_type=PydanticUndefined, when_used='json-unless-none'):
126
"""
127
Initialize serializer.
128
129
Args:
130
func: Serialization function
131
return_type: Return type annotation
132
when_used (str): When to use serializer
133
"""
134
135
class WrapSerializer:
136
"""
137
Serializer that wraps default serialization.
138
"""
139
140
def __init__(self, func, *, return_type=PydanticUndefined, when_used='json-unless-none'):
141
"""
142
Initialize serializer.
143
144
Args:
145
func: Serialization function
146
return_type: Return type annotation
147
when_used (str): When to use serializer
148
"""
149
150
class BeforeSerializer:
151
"""
152
Serializer that runs before default serialization.
153
"""
154
155
def __init__(self, func, *, when_used='json-unless-none'):
156
"""
157
Initialize serializer.
158
159
Args:
160
func: Serialization function
161
when_used (str): When to use serializer
162
"""
163
164
class AfterSerializer:
165
"""
166
Serializer that runs after default serialization.
167
"""
168
169
def __init__(self, func, *, return_type=PydanticUndefined, when_used='json-unless-none'):
170
"""
171
Initialize serializer.
172
173
Args:
174
func: Serialization function
175
return_type: Return type annotation
176
when_used (str): When to use serializer
177
"""
178
```
179
180
### Field and Alias Configuration
181
182
Advanced field configuration including aliases and serialization control.
183
184
```python { .api }
185
class AliasGenerator:
186
"""Base class for alias generators."""
187
188
def generate_alias(self, field_name: str) -> str:
189
"""
190
Generate alias for field name.
191
192
Args:
193
field_name (str): Original field name
194
195
Returns:
196
str: Generated alias
197
"""
198
199
def alias_generator(func):
200
"""
201
Create alias generator from function.
202
203
Args:
204
func: Function that takes field name and returns alias
205
206
Returns:
207
AliasGenerator instance
208
"""
209
210
class AliasChoices:
211
"""
212
Multiple alias choices for a field.
213
"""
214
215
def __init__(self, *choices):
216
"""
217
Initialize with alias choices.
218
219
Args:
220
*choices: Alias options
221
"""
222
223
class AliasPath:
224
"""
225
Path-based alias for nested data extraction.
226
"""
227
228
def __init__(self, *path):
229
"""
230
Initialize with path components.
231
232
Args:
233
*path: Path components for nested access
234
"""
235
236
### Alias Generator Functions
237
238
Built-in functions for common alias generation patterns.
239
240
```python { .api }
241
def to_pascal(snake_str):
242
"""
243
Convert snake_case string to PascalCase.
244
245
Args:
246
snake_str (str): String in snake_case format
247
248
Returns:
249
str: String in PascalCase format
250
251
Example:
252
to_pascal('user_name') -> 'UserName'
253
"""
254
255
def to_camel(snake_str):
256
"""
257
Convert snake_case string to camelCase.
258
259
Args:
260
snake_str (str): String in snake_case format
261
262
Returns:
263
str: String in camelCase format
264
265
Example:
266
to_camel('user_name') -> 'userName'
267
"""
268
269
def to_snake(camel_str):
270
"""
271
Convert PascalCase or camelCase string to snake_case.
272
273
Args:
274
camel_str (str): String in PascalCase or camelCase format
275
276
Returns:
277
str: String in snake_case format
278
279
Example:
280
to_snake('UserName') -> 'user_name'
281
to_snake('userName') -> 'user_name'
282
"""
283
```
284
285
### Core Schema Classes
286
287
Core classes from pydantic-core that are part of the serialization API.
288
289
```python { .api }
290
class SerializationInfo:
291
"""
292
Information available during serialization.
293
"""
294
295
@property
296
def include(self):
297
"""set | dict | None: Fields to include"""
298
299
@property
300
def exclude(self):
301
"""set | dict | None: Fields to exclude"""
302
303
@property
304
def context(self):
305
"""dict | None: Serialization context"""
306
307
@property
308
def mode(self):
309
"""str: Serialization mode"""
310
311
@property
312
def by_alias(self):
313
"""bool: Whether to use aliases"""
314
315
class FieldSerializationInfo:
316
"""
317
Information available during field serialization.
318
"""
319
320
@property
321
def field_name(self):
322
"""str: Field name"""
323
324
@property
325
def by_alias(self):
326
"""bool: Whether to use aliases"""
327
328
class SerializerFunctionWrapHandler:
329
"""
330
Handler for wrap serializers.
331
"""
332
333
def __call__(self, value):
334
"""
335
Call the wrapped serializer.
336
337
Args:
338
value: Value to serialize
339
340
Returns:
341
Serialized value
342
"""
343
```
344
345
## Usage Examples
346
347
### Computed Fields
348
349
```python
350
from pydantic import BaseModel, computed_field
351
from typing import Optional
352
353
class Person(BaseModel):
354
first_name: str
355
last_name: str
356
birth_year: int
357
358
@computed_field
359
@property
360
def full_name(self) -> str:
361
return f"{self.first_name} {self.last_name}"
362
363
@computed_field
364
@property
365
def age(self) -> int:
366
from datetime import date
367
return date.today().year - self.birth_year
368
369
# Usage
370
person = Person(
371
first_name="John",
372
last_name="Doe",
373
birth_year=1990
374
)
375
376
print(person.full_name) # "John Doe"
377
print(person.age) # Current age
378
print(person.model_dump()) # Includes computed fields
379
```
380
381
### Model Configuration
382
383
```python
384
from pydantic import BaseModel, ConfigDict
385
386
class StrictModel(BaseModel):
387
model_config = ConfigDict(
388
strict=True, # Strict validation
389
extra='forbid', # Forbid extra fields
390
frozen=True, # Immutable after creation
391
validate_assignment=True, # Validate assignments
392
str_strip_whitespace=True # Strip string whitespace
393
)
394
395
name: str
396
value: int
397
398
# Usage
399
model = StrictModel(name=" test ", value=42)
400
print(model.name) # "test" (whitespace stripped)
401
402
# This would raise ValidationError due to strict mode
403
# model = StrictModel(name="test", value="42") # string instead of int
404
405
# This would raise ValidationError due to extra='forbid'
406
# model = StrictModel(name="test", value=42, extra_field="not allowed")
407
```
408
409
### Field Serializers
410
411
```python
412
from pydantic import BaseModel, field_serializer
413
from datetime import datetime
414
from typing import Optional
415
416
class Event(BaseModel):
417
name: str
418
timestamp: datetime
419
metadata: Optional[dict] = None
420
421
@field_serializer('timestamp')
422
def serialize_timestamp(self, value: datetime) -> str:
423
return value.strftime('%Y-%m-%d %H:%M:%S UTC')
424
425
@field_serializer('metadata', when_used='json')
426
def serialize_metadata(self, value: Optional[dict]) -> Optional[str]:
427
if value is None:
428
return None
429
import json
430
return json.dumps(value, sort_keys=True)
431
432
# Usage
433
event = Event(
434
name="Conference",
435
timestamp=datetime(2023, 12, 25, 10, 30),
436
metadata={"location": "New York", "capacity": 100}
437
)
438
439
print(event.model_dump_json())
440
# Custom serialization applied to timestamp and metadata
441
```
442
443
### Model Serializers
444
445
```python
446
from pydantic import BaseModel, model_serializer
447
448
class APIResponse(BaseModel):
449
success: bool
450
data: dict
451
message: str
452
453
@model_serializer
454
def serialize_model(self):
455
# Custom serialization logic
456
result = {
457
'status': 'ok' if self.success else 'error',
458
'payload': self.data,
459
'info': self.message
460
}
461
462
# Add timestamp
463
from datetime import datetime
464
result['timestamp'] = datetime.utcnow().isoformat()
465
466
return result
467
468
# Usage
469
response = APIResponse(
470
success=True,
471
data={'user_id': 123, 'name': 'John'},
472
message='User retrieved successfully'
473
)
474
475
print(response.model_dump())
476
# Uses custom serialization format
477
```
478
479
### Alias Configuration
480
481
```python
482
from pydantic import BaseModel, Field, AliasPath, AliasChoices
483
484
class UserData(BaseModel):
485
user_id: int = Field(alias='id')
486
full_name: str = Field(alias=AliasChoices('fullName', 'full_name', 'name'))
487
address: str = Field(alias=AliasPath('location', 'address'))
488
489
class Config:
490
populate_by_name = True # Allow both field name and alias
491
492
# Usage with different alias formats
493
data1 = {'id': 123, 'fullName': 'John Doe', 'location': {'address': '123 Main St'}}
494
data2 = {'user_id': 456, 'full_name': 'Jane Smith', 'location': {'address': '456 Oak Ave'}}
495
496
user1 = UserData(**data1)
497
user2 = UserData(**data2)
498
499
print(user1.model_dump(by_alias=True)) # Uses aliases in output
500
```
501
502
### Functional Serializers with Annotated
503
504
```python
505
from pydantic import BaseModel, PlainSerializer, field_serializer
506
from typing import Annotated
507
from decimal import Decimal
508
509
def money_serializer(value: Decimal) -> str:
510
"""Serialize decimal as currency string."""
511
return f"${value:.2f}"
512
513
class Invoice(BaseModel):
514
amount: Annotated[Decimal, PlainSerializer(money_serializer, when_used='json')]
515
tax: Decimal
516
517
@field_serializer('tax', when_used='json')
518
def serialize_tax(self, value: Decimal) -> str:
519
return f"${value:.2f}"
520
521
# Usage
522
invoice = Invoice(amount=Decimal('100.50'), tax=Decimal('8.25'))
523
print(invoice.model_dump_json())
524
# {"amount": "$100.50", "tax": "$8.25"}
525
```
526
527
### Configuration Inheritance
528
529
```python
530
from pydantic import BaseModel, ConfigDict
531
532
class BaseConfig(BaseModel):
533
model_config = ConfigDict(
534
str_strip_whitespace=True,
535
validate_assignment=True,
536
frozen=True
537
)
538
539
class APIModel(BaseConfig):
540
model_config = ConfigDict(
541
# Inherits from BaseConfig and adds:
542
extra='forbid',
543
alias_generator=lambda field_name: field_name.replace('_', '-')
544
)
545
546
user_id: int
547
user_name: str
548
549
# Usage
550
model = APIModel(user_id=123, **{'user-name': ' John '})
551
print(model.user_name) # "John" (whitespace stripped)
552
print(model.model_dump(by_alias=True)) # {'user-id': 123, 'user-name': 'John'}
553
```
554
555
### Alias Generator Functions Usage
556
557
```python
558
from pydantic import BaseModel, ConfigDict, Field
559
from pydantic.alias_generators import to_camel, to_pascal, to_snake
560
561
class APIModel(BaseModel):
562
model_config = ConfigDict(alias_generator=to_camel)
563
564
user_id: int
565
user_name: str
566
created_at: str
567
568
# Field names are automatically converted to camelCase
569
data = {'userId': 123, 'userName': 'John', 'createdAt': '2023-12-25T10:30:00Z'}
570
model = APIModel(**data)
571
572
print(model.model_dump(by_alias=True))
573
# {'userId': 123, 'userName': 'John', 'createdAt': '2023-12-25T10:30:00Z'}
574
575
# Manual alias generation
576
class CustomModel(BaseModel):
577
snake_case_field: str = Field(alias=to_pascal('snake_case_field')) # 'SnakeCaseField'
578
another_field: int = Field(alias=to_camel('another_field')) # 'anotherField'
579
580
# Convert between naming conventions
581
original_name = 'user_profile_data'
582
camel_name = to_camel(original_name) # 'userProfileData'
583
pascal_name = to_pascal(original_name) # 'UserProfileData'
584
back_to_snake = to_snake(pascal_name) # 'user_profile_data'
585
586
print(f"Original: {original_name}")
587
print(f"Camel: {camel_name}")
588
print(f"Pascal: {pascal_name}")
589
print(f"Back to snake: {back_to_snake}")
590
```