Implementing Computed Fields
Computed fields allow you to include derived values—such as Python properties or cached properties—in the serialized output of your objects. These fields are calculated during serialization and are not part of the validation schema.
Defining Computed Fields in Models
To include a computed field in a model, define it using core_schema.computed_field within the computed_fields list of a model_fields_schema.
from functools import cached_property
from pydantic_core import SchemaSerializer, core_schema
class Model:
def __init__(self, x: int, y: int):
self.x = x
self.y = y
@cached_property
def y_formatted(self) -> str:
return f'{self.y:_}'
schema = core_schema.model_schema(
Model,
core_schema.model_fields_schema(
{
'x': core_schema.model_field(core_schema.int_schema()),
'y': core_schema.model_field(core_schema.int_schema()),
},
computed_fields=[
core_schema.computed_field('y_formatted', core_schema.str_schema())
],
)
)
serializer = SchemaSerializer(schema)
instance = Model(x=1000, y=2000)
assert serializer.to_python(instance) == {
'x': 1000,
'y': 2000,
'y_formatted': '2_000'
}
Using Computed Fields with Dataclasses
For dataclasses, computed fields are added to the dataclass_args_schema. The property_name must match the name of a @property defined on the dataclass.
import dataclasses
from pydantic_core import SchemaSerializer, core_schema
@dataclasses.dataclass
class FooProp:
a: str
b: bytes
@property
def c(self) -> str:
return f'{self.a} {self.b.decode()}'
schema = core_schema.dataclass_schema(
FooProp,
core_schema.dataclass_args_schema(
'FooProp',
[
core_schema.dataclass_field(name='a', schema=core_schema.str_schema()),
core_schema.dataclass_field(name='b', schema=core_schema.bytes_schema()),
],
computed_fields=[core_schema.computed_field('c', core_schema.str_schema())],
),
['a', 'b'],
)
serializer = SchemaSerializer(schema)
instance = FooProp(a='hello', b=b'more')
assert serializer.to_python(instance) == {
'a': 'hello',
'b': b'more',
'c': 'hello more'
}
Customizing Serialization
Using Aliases
You can use the alias parameter to change the key name used in the serialized output.
schema = core_schema.model_fields_schema(
{'x': core_schema.model_field(core_schema.int_schema())},
computed_fields=[
core_schema.computed_field(
'x_plus_one',
core_schema.int_schema(),
alias='x1'
)
],
)
# Serialized output will use 'x1' instead of 'x_plus_one'
Conditional Serialization
The serialization_exclude_if parameter allows you to skip a computed field based on its value. The predicate function receives the result of the property.
def exclude_if_none(value):
return value is None
schema = core_schema.computed_field(
'maybe_value',
core_schema.str_schema(),
serialization_exclude_if=exclude_if_none
)
Troubleshooting
Computed Fields Missing in Output
If your computed fields are not appearing in the serialized output, check the following:
- Round Trip Mode: Computed fields are automatically excluded if
round_trip=Trueis passed to the serializer (e.g.,serializer.to_python(obj, round_trip=True)). This is because computed fields cannot be validated back into the object. - Explicit Exclusion: Ensure
exclude_computed_fields=Trueis not being passed to the serialization method. - Schema Placement: Computed fields are only supported within
model_fields_schema,dataclass_args_schema, andtyped_dict_schema. They will not function if placed in other schema types. - Property Access:
pydantic-coreusesgetattr(instance, property_name)to retrieve the value. Ensure the property is accessible and does not raise an exception during access.