我会为此查看 dataclass-wizard 库。它与 Python 中内置的 dataclasses 模块配合得很好。它支持每个字段的多个别名(或键映射),以及在这种情况下我们可能想要的单向别名 - 例如。如果我们想允许fullname 到name 字段的额外映射,但使用默认键name 进行序列化。
在下面的示例中,我还添加了一个 __future__ 导入,它在 Python 3.7 或更高版本中受支持。这主要是为了支持前向引用的使用;如果没有这个未来的导入,我们将需要明确定义前向引用,例如。喜欢List['Student']。
from __future__ import annotations
from dataclasses import dataclass
from typing import List
from dataclass_wizard import json_key
from typing_extensions import Annotated
@dataclass
class Container:
students: List[Student]
@dataclass
class Student:
id: int
name: Annotated[str, json_key('fullname')]
gender: Annotated[str, json_key('sex')]
在上面的注释中,将其声明为json_key('fullname') 是json_key('name', 'fullname', all=True) 的简写,这也是多个别名可以映射到一个字段的方式。
请注意,如果您只打算支持 Python 3.9 或更高版本,您可以进行以下更改:
- 改为从
typing 模块导入Annotated
- 删除
from typing import List 导入并定义像list[Student] 这样的注解
这是测试上述代码的示例用法:
if __name__ == '__main__':
from dataclass_wizard import asdict, fromdict, fromlist
source_1 = {
"students": [{
"id": 129939,
"name": "Alice",
"gender": "female",
}]
}
source_2 = {
"students": [{
"id": 129940,
"fullname": "Johnny",
"sex": "male",
}]
}
c1 = fromdict(Container, source_1)
print(c1)
# Container(students=[Student(id=129939, name='Alice', gender='female')])
c2 = fromdict(Container, source_2)
print(c2)
# Container(students=[Student(id=129940, name='Johnny', gender='male')])
# alternatively, if you just need a list of the `Student` instances:
students = fromlist(Student, source_1['students'])
print(students)
# [Student(id=129939, name='Alice', gender='female')]
# assert we get the same data when serializing the Container instance as a
# Python dict object.
serialized_dict = asdict(c1)
assert serialized_dict == source_1