Pydantic model field: convert empty string to None #2687
-
It is very common for API to accept empty strings for query params as None, I'm trying to find a generic way to define fields to be coerced to None.
Right now above field would fail if empty string is passed as not a valid value for int. I'd like it to be treated as similar to Optional. Is there anything built-in? is it possible to define a custom type something like |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 11 replies
-
Hi @natasha-aleksandrova from typing import Optional, Union
from pydantic import BaseModel
from pydantic.validators import str_validator
def empty_to_none(v: str) -> Optional[str]:
if v == '':
return None
return v
class EmptyStrToNone(str):
@classmethod
def __get_validators__(cls):
yield str_validator
yield empty_to_none
class M(BaseModel):
x: Union[None, int, EmptyStrToNone]
assert M(x=None).x is None
assert M(x=0).x == 0
assert M(x='').x is None
assert M(x='q').x == 'q' or add a validator from typing import Union
from pydantic import BaseModel as PydanticBaseModel, validator
class BaseModel(PydanticBaseModel):
@validator('*')
def empty_str_to_none(cls, v):
if v == '':
return None
return v
class M(BaseModel):
x: Union[None, int, str]
assert M(x=None).x is None
assert M(x=0).x == 0
assert M(x='').x is None
assert M(x='q').x == 'q' In the second case I created a custom |
Beta Was this translation helpful? Give feedback.
-
Hello ! I am using this way, I add this comment because today I searched for the same thing hahaha and I found another way to do it. from pydantic import BaseModel, constr
class CustomerAddress(BaseModel):
countrySubDivisionMajorName: constr(min_length=1)
districtReference: constr(min_length=1)
residentialStreetName: constr(min_length=1)
residentialStreetNumber: constr(min_length=1) |
Beta Was this translation helpful? Give feedback.
-
I've found that using the from typing import Annotated, TypeAlias
from pydantic import BeforeValidator
def _empty_str_to_none(v: str | None) -> None:
if v is None:
return None
if v == '':
return None
raise ValueError('Value is not empty') # Not str or None, Fall to next type. e.g. Decimal, or a non-empty str
EmptyStrToNone: TypeAlias = Annotated[None, BeforeValidator(_empty_str_to_none)] Used like this: class MyExampleModel(BaseModel):
places: List[str]
dates: List[dt.date]
codes: List[str]
prices: List[EmptyStrToNone | Decimal] This solves static typechecking ala pyright/mypy as well as having Pydantic to the right thing at runtime. And can be used just as a type hint throughout codebase. |
Beta Was this translation helpful? Give feedback.
Hi @natasha-aleksandrova
You can achieve what you want by either create a custom type
or add a validator