如何解决如何将 JSON 转换为具有类型信息和枚举的对象?
将一些 JSON 编组到强类型 Python 对象中的最佳方法是什么,该对象比仅仅转换为类似 dict
的对象提供更多的数据保证?
我有一些来自外部 API 的 JSON,如下所示:
{
"Name of Event": {
"start": "2021-01-01 00:00:00","event_type": 1
},"Another Event": {
"start": "2021-01-01 00:00:00","event_type": 2,}
}
(重要的是要知道我正在使用的实际 JSON 要复杂得多(并且嵌套很深),但基本上它是一个结构非常好的东西,一直都有已知类型。)
我可以做一些简单的事情:
for name,event in json.loads(data):
do_things(name,event['start'],event['event_type'])
但这感觉相当毛茸茸,并且在写入时或运行时都没有让我的程序进行类型检查。
在我处理这个 JSON 的代码中,我想使用正确类型的东西。但我不想写大量的样板。
我可以做一些非常明确的事情,比如:
DATE_FORMAT = "%y-%m-%d %H:%M:%S"
class EventType:
FREE_FOR_ALL = 1
CLOSED_REGISTRATION = 2
class Event:
__slots__ = ["start","event_type"]
start: datetime.datetime
event_type: EventType
def __init__(self,start,event_type):
self.start = datetime.datetime.strptime(start,DATE_FORMAT)
self.event_type = EventType(event_type)
def __str__(self):
return str(self.__dict__)
def __repr__(self):
return str(self.__dict__)
APIResponse = Dict[str,Event]
for name,raw_event in data:
event = Event(**data)
do_things(name,event)
就目前而言这很好,但是一旦你有十几个类,每个类都有十几个属性,它开始看起来像很多样板。特别是我觉得我对每个属性定义了两次,违反了 DRY。一次在课堂上,一次在__init__
。
(对于 API 在任何给定的枚举中添加新选项等情况,我也有点担心这有点“脆弱”,但这是一个小得多的担忧,因为我希望 API 更改需要更改我的代码。)
我想知道我是否可以使用任何魔法来实现它,所以我只需要在一个地方定义每个字段,但仍然可以获得良好的类型检查和运行时保证数据采用我期望的形式?
我查看了 dataclasses
,但似乎我无法将 JSON 的简单字符串/int 输入干扰到枚举、日期时间等中。我可以使用 InitVar
来标记许多输入为“仅__init__
”,然后使用 __post_init__
用我的数据的强类型版本填充具有不同名称的其他字段。但大多数这些字段的“正确”名称是它在 JSON 中已有的名称(我不想写 event.event_type_typed_version
)。
理想情况下,我会这样写:
@magic_annotation
class Event:
start: datetime.datetime
event_type: EventType
for name,event)
并且不需要任何其他东西。 magic_annotation
是否存在?有没有完全不同的方法来解决这个问题?
解决方法
听起来你在关注pydantic。
from datetime import datetime
from enum import Enum
from pydantic import BaseModel
class EventType(Enum):
FREE_FOR_ALL = 1
CLOSED_REGISTRATION = 2
class Event(BaseModel):
start: datetime
event_type: EventType
event = Event.parse_obj({
"start": "2021-01-01 00:00:00","event_type": 1
})
print(repr(event))
# Event(start=datetime.datetime(2021,1,0),event_type=<EventType.FREE_FOR_ALL: 1>)
Pydantic 会根据您的类属性的类型注释自动转换您的输入。对于日期时间,它支持标准 ISO 8601 格式。对于枚举,它会自动从枚举值转换。 Check it out!(无关联,只是粉丝。)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。