How to change date format in pydantic for validation and serialization? For validation I am using @validator
. Is there an solution for both cases?
I think that pre validator can help here.
from datetime import datetime, date
from pydantic import BaseModel, validator
class OddDate(BaseModel):
birthdate: date
@validator("birthdate", pre=True)
def parse_birthdate(cls, value):
return datetime.strptime(
value,
"%d/%m/%Y"
).date()
if __name__ == "__main__":
odd_date = OddDate(birthdate="12/04/1992")
print(odd_date.json()) #{"birthdate": "1992-04-12"}
You can implement a custom json serializer by using pydantic's custom json encoders . Then, together with pydantic's custom validator , you can have both functionalities.
from datetime import datetime, timezone
from pydantic import BaseModel, validator
def convert_datetime_to_iso_8601_with_z_suffix(dt: datetime) -> str:
return dt.strftime('%Y-%m-%dT%H:%M:%SZ')
def transform_to_utc_datetime(dt: datetime) -> datetime:
return dt.astimezone(tz=timezone.utc)
class DateTimeSpecial(BaseModel):
datetime_in_utc_with_z_suffix: datetime
# custom input conversion for that field
_normalize_datetimes = validator(
"datetime_in_utc_with_z_suffix",
allow_reuse=True)(transform_to_utc_datetime)
class Config:
json_encoders = {
# custom output conversion for datetime
datetime: convert_datetime_to_iso_8601_with_z_suffix
}
if __name__ == "__main__":
special_datetime = DateTimeSpecial(datetime_in_utc_with_z_suffix="2042-3-15T12:45+01:00") # note the different timezone
# input conversion
print(special_datetime.datetime_in_utc_with_z_suffix) # 2042-03-15 11:45:00+00:00
# output conversion
print(special_datetime.json()) # {"datetime_in_utc_with_z_suffix": "2042-03-15T11:45:00Z"}
This variant also works in fastapi's serializer where I am actually using it in that way.
In case you don't necessarily want to apply this behavior to all datetimes, you can create a custom type extending datetime
. For example, to make a custom type that always ensures we have a datetime with tzinfo set to UTC:
from datetime import datetime, timezone
from pydantic.datetime_parse import parse_datetime
class utc_datetime(datetime):
@classmethod
def __get_validators__(cls):
yield parse_datetime # default pydantic behavior
yield cls.ensure_tzinfo
@classmethod
def ensure_tzinfo(cls, v):
# if TZ isn't provided, we assume UTC, but you can do w/e you need
if v.tzinfo is None:
return v.replace(tzinfo=timezone.utc)
# else we convert to utc
return v.astimezone(timezone.utc)
@staticmethod
def to_str(dt:datetime) -> str:
return dt.isoformat() # replace with w/e format you want
Then your pydantic models would look like:
from pydantic import BaseModel
class SomeObject(BaseModel):
some_datetime_in_utc: utc_datetime
class Config:
json_encoders = {
utc_datetime: utc_datetime.to_str
}
Going this route helps with reusability and separation of concerns:)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.