Aviad Rozenhek
Aviad Rozenhek

Reputation: 2429

How to Include a Computed Field Decorated as `@property` in Pydantic v2 Schema for JSON Schema and Serialization?

I'm working with Pydantic v2 and trying to include a computed field in both the schema generated by .model_json_schema() and the serialized output from .model_dump_json(). I've decorated the computed field with @property, but it seems that Pydantic's schema generation and serialization processes do not automatically include these properties.

Goal:

Current Approach: Here's a simplified version of my model where I've defined a computed property full_name:

from pydantic import BaseModel, computed_field

class User(BaseModel):
    first_name: str
    last_name: str

    @computed_field
    @property
    def full_name(self) -> str:
        return f"{self.first_name} {self.last_name}"

Issues:

To illustrate, here's how I'm attempting to generate the schema and serialize the model:

user_instance = User(first_name="John", last_name="Doe")

# Attempt to generate JSON schema
json_schema = User.model_json_schema()
print(json_schema)  # 'full_name' is not included

# Attempt to serialize the model
serialized_output = user_instance.json()
print(serialized_output)  # 'full_name' IS included

Question: How can I modify my Pydantic model or process to ensure that the full_name computed property is included both in the schema and the serialized output? I am looking for a solution that works seamlessly with Pydantic v2's features and conventions.

Upvotes: 0

Views: 1342

Answers (1)

Jonny Henly
Jonny Henly

Reputation: 4233

The mode keyword argument to model_json_schema() is 'validation' by default and doesn't include computed fields, mode='serialization' does.

JsonSchemaMode module-attribute

JsonSchemaMode = Literal['validation', 'serialization']

A type alias that represents the mode of a JSON schema; either 'validation' or 'serialization'.

For some types, the inputs to validation differ from the outputs of serialization. For example, computed fields will only be present when serializing, and should not be provided when validating. This flag provides a way to indicate whether you want the JSON schema required for validation inputs, or that will be matched by serialization outputs.

from pydantic import BaseModel, computed_field

class User(BaseModel):
    first_name: str
    last_name: str

    @computed_field
    @property
    def full_name(self) -> str:
        return f"{self.first_name} {self.last_name}"

if __name__ == '__main__':
    json_schema = User.model_json_schema()
    print(json_schema)  # 'full_name' is not included
    
    json_schema_full = User.model_json_schema(mode='serialization')
    print(json_schema_full)  # 'full_name' is included

Output:

{'properties': {'first_name': {'title': 'First Name', 'type': 'string'}, 'last_name': {'title': 'Last Name', 'type': 'string'}}, 'required': ['first_name', 'last_name'], 'title': 'User', 'type': 'object'}
{'properties': {'first_name': {'title': 'First Name', 'type': 'string'}, 'last_name': {'title': 'Last Name', 'type': 'string'}, 'full_name': {'readOnly': True, 'title': 'Full Name', 'type': 'string'}}, 'required': ['first_name', 'last_name', 'full_name'], 'title': 'User', 'type': 'object'}

Related GitHub issue: Including computed_field in JSON schema?

Upvotes: 1

Related Questions