I have a model with many fields that can have None value. Pydantic (v2) provides easy way to do two things
model_dump
using the include
argument with a list of fields.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 I include both exclude_none
and include
arguments, the exclude part wins.
The following unit test will fail
import unittest
from pydantic import BaseModel
class A(BaseModel):
a: str | None
class PydanticIncludeAndExcludedNoneTestCase(unittest.TestCase):
""" Shows that `exclude_none` wins over `include` when dumping the pydantic v2 model """
def test_simple(self):
item = A(a=None)
d = item.model_dump(include={'a'}, exclude_none=True)
self.assertEqual(d['a'], None) # add assertion here
if __name__ == '__main__':
unittest.main()
Is this what you need?
from pydantic import BaseModel, model_serializer
class A(BaseModel):
a: str | None
b: str | None
@model_serializer(mode="wrap")
def _serialize(self, handler):
d = handler(self)
d['a'] = self.a
return d
a1 = A(a=None, b=None)
a2 = A(a="strrrr", b=None)
print(a1.model_dump(exclude_none=True))
print(a2.model_dump(exclude_none=True))
Output:
{'a': None}
{'a': 'strrrr'}
Or you can modify it to have the list of mandatory fields as a parameter of model:
from pydantic import BaseModel, model_serializer
class A(BaseModel):
a: str | None
b: str | None
c: int | None
_always_serialize_fields: list["str"] = ["a", "c"]
@model_serializer(mode="wrap")
def _serialize(self, handler):
d = handler(self)
for f in self._always_serialize_fields:
d[f] = getattr(self, f)
return d
a1 = A(a=None, b = None, c=None)
a2 = A(a="strrrr", b=None, c=None)
print(a1.model_dump(exclude_none=True))
print(a2.model_dump(exclude_none=True))
Output:
{'a': None, 'c': None}
{'a': 'strrrr', 'c': None}