【发布时间】:2021-06-07 10:36:36
【问题描述】:
如何更改 pydantic 中的日期格式以进行验证和序列化?
为了验证,我使用@validator。两种情况都有解决方案吗?
【问题讨论】:
-
@alex_noname 它在 data.json() 中有效,但在 fastapi 序列化程序中无效。
标签: python python-3.x pydantic
如何更改 pydantic 中的日期格式以进行验证和序列化?
为了验证,我使用@validator。两种情况都有解决方案吗?
【问题讨论】:
标签: python python-3.x pydantic
如果您不一定要将此行为应用于所有日期时间,您可以创建一个扩展 datetime 的自定义类型。例如,要创建一个始终确保我们有一个将 tzinfo 设置为 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
那么你的 pydantic 模型看起来像:
from pydantic import BaseModel
class SomeObject(BaseModel):
some_datetime_in_utc: utc_datetime
class Config:
json_encoders = {
utc_datetime: utc_datetime.to_str
}
走这条路有助于可重用性和关注点分离:)
【讨论】:
json 函数,覆盖默认值。我希望有更好的方法,特别是因为在调用 @987654325 时没有考虑编码器@ 代替。
您可以使用 pydantic's custom json encoders 实现自定义 json 序列化程序。然后,与pydantic's custom validator 一起,您可以同时拥有这两种功能。
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"}
这个变体也适用于我实际以这种方式使用它的 fastapi 的序列化程序。
【讨论】:
我认为预验证器在这里可以提供帮助。
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"}
【讨论】: