You could exclude only optional model fields that unset by making of union of model fields that are set and those that are not None.

Pydantic provides the following arguments for exporting method model.dict(...):

exclude_unset: whether fields which were not explicitly set when creating the model should be excluded from the returned dictionary; default False.

exclude_none: whether fields which are equal to None should be excluded from the returned dictionary; default False

To make union of two dicts we can use the expression a = {**b, **c} (values from c overwrites values from b). Note that since Python 3.9 it could be done just as a = b | c.

from pydantic import BaseModel
from typing import Optional
from pydantic.json import pydantic_encoder
import json


class Foo(BaseModel):
    x: int
    y: int = 42
    z: Optional[int]

def exclude_optional_dict(model: BaseModel):
    return {**model.dict(exclude_unset=True), **model.dict(exclude_none=True)}

def exclude_optional_json(model: BaseModel):
    return json.dumps(exclude_optional_dict(model), default=pydantic_encoder)
    


print(exclude_optional_json(Foo(x=3)))  # {"x": 3, "y": 42}
print(exclude_optional_json(Foo(x=3, z=None)))  # {"x": 3, "z": null, "y": 42}
print(exclude_optional_json(Foo(x=3, z=77)))  # {"x": 3, "z": 77, "y": 42}

Update

In order for the approach to work with nested models, we need to do a deep union( or merge) of two dictionaries, like so:

def union(source, destination):
    for key, value in source.items():
        if isinstance(value, dict):
            node = destination.setdefault(key, {})
            union(value, node)
        else:
            destination[key] = value

    return destination

def exclude_optional_dict(model: BaseModel):
    return union(model.dict(exclude_unset=True), model.dict(exclude_none=True))

class Foo(BaseModel):
    x: int
    y: int = 42
    z: Optional[int]

class Bar(BaseModel):
    a: int
    b: int = 52
    c: Optional[int]
    d: Foo


print(exclude_optional_json(Bar(a=4, d=Foo(x=3))))
print(exclude_optional_json(Bar(a=4, c=None, d=Foo(x=3, z=None))))
print(exclude_optional_json(Bar(a=4, c=78, d=Foo(x=3, z=77))))
{"a": 4, "b": 52, "d": {"x": 3, "y": 42}}
{"a": 4, "b": 52, "d": {"x": 3, "y": 42, "z": null}, "c": null}
{"a": 4, "b": 52, "c": 78, "d": {"x": 3, "y": 42, "z": 77}}
Answer from alex_noname on Stack Overflow
🌐
GitHub
github.com › pydantic › pydantic › discussions › 5461
`exclude_none` for specific fields only · pydantic/pydantic · Discussion #5461
I'll try to see if this can be solved by #12056 and #10961. Beta Was this translation helpful? Give feedback. ... There was an error while loading. Please reload this page. Something went wrong. There was an error while loading. Please reload this page. ... Thanks to @andresliszt, this should now be possible with #12141, that will land in the upcoming 2.12 version: from pydantic import BaseModel, Field class Model(BaseModel): a: int | None = Field(exclude_if=lambda v: v is None) Model(a=None).model_dump() # {}
Author   pydantic
🌐
Pydantic
docs.pydantic.dev › latest › concepts › fields
Fields - Pydantic Validation
from pydantic import BaseModel, ... ... In Pydantic V1, a type annotated as Any or wrapped by Optional would be given an implicit default of None even if no default was explicitly specified....
Discussions

Pydantic v2 exclude parameter in Field and Annotated
I think that it's because you annotated it as Optional[Annotated[User, Field(exclude=True)]]. That basically means either None or annotated User. Try this Annotated[Optional[User], Field(exclude=True)] Your typing is kind of weird, you say you want it to be either None or excluded. And I think pydantic cannot resolve it because it's not applied to all the possibilities in the field. If I should guess, pydantic doesn't even check for Annotated when it's not the root type as it doesn't make much sense. More on reddit.com
🌐 r/learnpython
5
1
January 1, 2024
python - In JSON created from a pydantic.BaseModel exclude Optional if not set - Stack Overflow
If there is any other solution to set z to optional in this sense, I would like to see it. ... You could exclude only optional model fields that unset by making of union of model fields that are set and those that are not None. Pydantic provides the following arguments for exporting method ... More on stackoverflow.com
🌐 stackoverflow.com
pydantic v2 python validation, how to dump some, not all fields with None value - Stack Overflow
Pydantic (v2) provides easy way to do two things · include certain fields only when calling model_dump using the include argument with a list of fields. not to include fields that have a None value by setting the exclude_none argument to True · What is the way to ensure some (but not others) fields are included even though they have the None value? If ... More on stackoverflow.com
🌐 stackoverflow.com
Struggling with Pydantic 'excludes'
Forgive me if this doesn't answer the question at hand, I'm doing my best with a short amount of time. It looks like the problem here is dealing with lists. To handle a list, you'll have to use a validator, as field will not peek into a list to check the elements inside. Here's the relevant docs: https://docs.pydantic.dev/usage/validators/ The tl;dr here is that you'll set up your model and then set up a validator by having the validator decorator and setting up the validation function beneath it. You'll also want to set for_each to true in the decorator so it knows to check each item in the list. So, as a big hammer approach, something like @validator('the_name_of_the_field_you_want_to_check', for_each=True) def scrub_children(cls, v): v.parent_node = None return v Might fix your problem. More on reddit.com
🌐 r/FastAPI
4
5
March 2, 2023
🌐
Pydantic
docs.pydantic.dev › 1.10 › usage › exporting_models
Exporting models - Pydantic
exclude_defaults: whether fields which are equal to their default values (whether set or otherwise) should be excluded from the returned dictionary; default False · exclude_none: whether fields which are equal to None should be excluded from the returned dictionary; default False
🌐
Reddit
reddit.com › r/learnpython › pydantic v2 exclude parameter in field and annotated
r/learnpython on Reddit: Pydantic v2 exclude parameter in Field and Annotated
January 1, 2024 -

I am playing around with Pydantic v2.5 and trying to see how the exclude works when set as a Field option. Let's imagine that I have a User BaseModel class and a Permissions BaseModel class. Both are used in the Config class.

We do not want to print the all User info, hence why I added the exclude in the Permissions class when the user is defined.

from typing import Annotated, Optional
from pydantic import BaseModel, Field


class User(BaseModel):
    name: str
    surname: str
    card_id: str


class Permissions(BaseModel):
    user: Annotated[User, Field(exclude=True)]
    config_rule: str


class Config:
    def __init__(self):
        self.user = User(**dict(name="Name", surname="Surname", card_id="12343545"))
        self.config_data = Permissions(user=self.user, config_rule="admin")

c = Config()
print(c.config_data.model_dump_json(indent=2))

In this case, the exclude set in the Permissions class seems to be working fine, in fact the print output is:

{
  "config_rule": "admin"
}

However, if I change the Permissions class with:

class Permissions(BaseModel):
    user: Optional[Annotated[User, Field(exclude=True)]]
    config_rule: str

The output is:

{
  "user": {
    "name": "Name",
    "surname": "Surname",
    "card_id": "12343545"
  },
  "config_rule": "admin"
}

And I am not sure I understand why. Any thoughts? Thanks.

🌐
Pydantic
docs.pydantic.dev › latest › concepts › serialization
Serialization - Pydantic Validation
exclude_defaults: Exclude all fields whose value compares equal to the default value (using the equality (==) comparison operator). exclude_none: Exclude all fields whose value is None.
Top answer
1 of 2
25

You could exclude only optional model fields that unset by making of union of model fields that are set and those that are not None.

Pydantic provides the following arguments for exporting method model.dict(...):

exclude_unset: whether fields which were not explicitly set when creating the model should be excluded from the returned dictionary; default False.

exclude_none: whether fields which are equal to None should be excluded from the returned dictionary; default False

To make union of two dicts we can use the expression a = {**b, **c} (values from c overwrites values from b). Note that since Python 3.9 it could be done just as a = b | c.

from pydantic import BaseModel
from typing import Optional
from pydantic.json import pydantic_encoder
import json


class Foo(BaseModel):
    x: int
    y: int = 42
    z: Optional[int]

def exclude_optional_dict(model: BaseModel):
    return {**model.dict(exclude_unset=True), **model.dict(exclude_none=True)}

def exclude_optional_json(model: BaseModel):
    return json.dumps(exclude_optional_dict(model), default=pydantic_encoder)
    


print(exclude_optional_json(Foo(x=3)))  # {"x": 3, "y": 42}
print(exclude_optional_json(Foo(x=3, z=None)))  # {"x": 3, "z": null, "y": 42}
print(exclude_optional_json(Foo(x=3, z=77)))  # {"x": 3, "z": 77, "y": 42}

Update

In order for the approach to work with nested models, we need to do a deep union( or merge) of two dictionaries, like so:

def union(source, destination):
    for key, value in source.items():
        if isinstance(value, dict):
            node = destination.setdefault(key, {})
            union(value, node)
        else:
            destination[key] = value

    return destination

def exclude_optional_dict(model: BaseModel):
    return union(model.dict(exclude_unset=True), model.dict(exclude_none=True))

class Foo(BaseModel):
    x: int
    y: int = 42
    z: Optional[int]

class Bar(BaseModel):
    a: int
    b: int = 52
    c: Optional[int]
    d: Foo


print(exclude_optional_json(Bar(a=4, d=Foo(x=3))))
print(exclude_optional_json(Bar(a=4, c=None, d=Foo(x=3, z=None))))
print(exclude_optional_json(Bar(a=4, c=78, d=Foo(x=3, z=77))))
{"a": 4, "b": 52, "d": {"x": 3, "y": 42}}
{"a": 4, "b": 52, "d": {"x": 3, "y": 42, "z": null}, "c": null}
{"a": 4, "b": 52, "c": 78, "d": {"x": 3, "y": 42, "z": 77}}
2 of 2
6

If you're using FastAPI then using exclude_none doesn't seem to work when a response_model is mentioned in the route decorator.

@app.post("/items/", response_model=Item)
async def create_item(item: Item):
    return item.dict(exclude_none=True)

Fast api seems to reprocess the dict with the pydantic model

So overriding the dict method in the model itself should work

def Item(BaseModel):
   name: str
   description: Optional[str]
   ...
   def dict(self, *args, **kwargs) -> Dict[str, Any]:
        kwargs.pop('exclude_none', None)
        return super().dict(*args, exclude_none=True, **kwargs)

(an actual solution would put this definition in separate subclass of BaseModel for reuse)

Note: just changing the default value of the exclude_none keyword argument is not enough: it seems FastAPI always sends exclude_none=False as an argument.


Source:
https://github.com/tiangolo/fastapi/issues/3314#issuecomment-962932368

🌐
Reddit
reddit.com › r/fastapi › struggling with pydantic 'excludes'
r/FastAPI on Reddit: Struggling with Pydantic 'excludes'
March 2, 2023 -

I'm building an API that deals with a bunch of related data structures. And I'm currently struggling with some of the intricacies of Pydantic. Here's my problem. I hope someone out there is able to help me out here! :)

Consider a Pydantic schema like this:

class Node(BaseModel):

    name: str

    uuid: UUID

    parent_node_uuid: UUID | None

With that it is possible to represent a hierarchical, tree-like data set. Individual node objects are related to each other through the parent_node_uuid property. Each parent node can have multiple children. But each child can only ever have a single parent. (in other words there is a self-referential one-to-many relationship)

Now, when outputting this data set through the api endpoint, I could simply use the above schema as my response_model. But instead I want to make the data more verbose and instead nest the model, so that the output of one node includes all the information about its parent and child nodes. The naive approach looks like this:

class Node(BaseModel):

    name: str

    uuid: UUID

    parent_node: "Node" | None = None

    child_nodes: List["Node"] = []

Unfortunately, this does not work as intended. When I try to pass sqlalchemy objects (which do have the required relationships set up) to this Pydantic schema, I'm running into an infinite recursion and python crashes. The reason is that the parent_node includes the main node object inits child_nodes property. Similarly, each child_node of our main node will have the main node set as their parent_node. - it's easy to see how Pydantic gets stuck in an infinite loop here.

There is a solution to one part of this problem:

class Node(BaseModel):

    name: str

    uuid: UUID

    parent_node: "Node" | None = Field(None, exclude={"child_nodes"}) 

    child_nodes: List["Node"] = []

Using the exclude option, we're able to remove the child_nodes from the parent. - That's one half of the issue resolved. The above model now works in cases where our main node doesn't have any children, but it has a parent. (more on this in the docs here)

Unfortunately though, this solution does not work with lists. I've tried the following without success:

class Node(BaseModel):

    name: str

    uuid: UUID

    parent_node: "Node" | None = Field(None, exclude={"child_nodes"}) 

    child_nodes: List["Node"] = Field([], exclude={"parent_node"})

*Does anyone know how I can get the exclude parameter to work when dealing with a List of models? *

Find elsewhere
🌐
GitHub
github.com › fastapi › fastapi › issues › 3314
How to exclude null value from pydantic model used by ...
May 31, 2021 - from typing import Optional from fastapi import Body, FastAPI from pydantic import BaseModel, Field · app = FastAPI() class Item(BaseModel): name: str description: Optional[str] = Field(None, title="The description of the item", max_length=300) price: float = Field(..., gt=0, description="The price must be greater than zero") tax: Optional[float] = None · @app.post("/items/") async def create_item(item: Item): return item · Problem - How to exclude optional fields from JSON when not supplied as part of the request.
Published   May 31, 2021
Author   karan-kumar-by
🌐
Medium
medium.com › @balakrishnamaduru › efficiently-filtering-non-none-values-from-nested-pydantic-models-5b86256ab681
Efficiently Filtering Non-None Values from Nested Pydantic Models | by Balakrishna Maduru | Medium
February 7, 2025 - This model has a method get_non_none_values to exclude any fields that are None: from pydantic import BaseModel from typing import Optional class MyModel(BaseModel): name: Optional[str] = None age: Optional[int] = None email: Optional[str] = ...
🌐
Medium
skaaptjop.medium.com › how-i-use-pydantic-unrequired-fields-so-that-the-schema-works-0010d8758072
How I use Pydantic unrequired fields without defaults | by Will van der Leij | Medium
May 22, 2024 - I would need to exclude_unset to make sure I don’t have a bunch of useless data in my serialized dict. This is not too bad because that is what I designed my schema to do… don’t give me data and I won’t have any data. But then instead of having biolerplate looking for if field is None: I’m just going to have to have boilerplate that asks if data.get(‘address’) etc.
🌐
Sentry
sentry.io › sentry answers › fastapi › exclude one or more fields in pydantic model from appearing in fastapi responses
Exclude one or more fields in Pydantic model from appearing in FastAPI responses | Sentry
This special typing form was proposed in PEP 593 and is used to add specific metadata to type declarations. This metadata is being used by libraries such as Pydantic to enable special behavior. In this case, we’ll use it to exclude the address and created_at fields from our API’s responses:
🌐
Helpmanual
pydantic-docs.helpmanual.io › usage › exporting_models
Serialization - Pydantic Validation
exclude_none: whether fields which are equal to None should be excluded from the returned dictionary; default False ... from pydantic import BaseModel class BarModel(BaseModel): whatever: int class FooBarModel(BaseModel): banana: float foo: str bar: BarModel m = FooBarModel(banana=3.14, ...
🌐
GitHub
github.com › samuelcolvin › pydantic › issues › 1862
Is it possible to exclude fields from the model itself when exporting them? (instead of dict(exclude=..)) · Issue #1862 · pydantic/pydantic
August 23, 2020 - (instead of dict(exclude=..))#1862 ... class MyCls(BaseModel): permissions: Permissions some_id: str = Field('') some_flag: bool = Field(False)
Author   arielb135
🌐
Roman Imankulov
roman.pt › posts › handling-unset-values-in-fastapi-with-pydantic
Handling Unset Values in Fastapi With Pydantic - Roman Imankulov
December 26, 2023 - class GetTasksFilter(BaseModel): text: str | None = None assigned_by: int | None = None due_date: datetime.datetime | None = None @app.get("/api/v1/tasks") def get_tasks(get_tasks_filter: GetTasksFilter): if get_tasks_filter.due_date is None: # Should I select tasks that don't have a due date set, # or should I not filter by due date at all? ... It turns out that Pydantic has a simple solution for that. Internally, it keeps a list of fields that were explicitly initialized, versus those that were initialized with a default or default_constructor args.
🌐
Stack Overflow
stackoverflow.com › questions › 76959287 › exclude-not-passed-fields-from-pydantic-2-2
python - Exclude not passed fields from Pydantic 2.2 - Stack Overflow
If Optional field passed even it was None keep this data ... Thank god they changed this in v2... Anyway, to your requirements: "If Optional field not passed - ignore it" And what is supposed to happen exactly? What value should the role field for example hold, if you initialize a UpdateUserPayload instance without providing a role value to the constructor? I am genuinely curious what you expect to happen. ... from pydantic import BaseModel, constr from typing import Optional class UpdateUserPayload(BaseModel): first_name: Optional[constr(min_length=1, max_length=150)] last_name: Optional[constr(min_length=1, max_length=150)] role: Optional[str] = None is_notifications: Optional[bool] = None data = {"first_name": "foo", "last_name": "bar"} UpdateUserPayload(**data).model_dump(exclude_unset=True)
🌐
Stack Overflow
stackoverflow.com › questions › 78651357 › always-apply-exclude-none-to-a-model-pydantic-1-10
python - always apply exclude_none to a model (Pydantic 1.10) - Stack Overflow
But if you decide to do this, try implementing a custom serialization method: from pydantic import BaseModel class Metadata(BaseModel): attr1: str attr2: int | None = None class Response(BaseModel): stuff1: int | None stuff2: int metadata: Metadata def as_dict(self) -> dict: """Custom method for serialization.""" response = self.dict(exclude={"metadata"}) response["metadata"] = self.metadata.dict(exclude_none=True) return response