枚举型的序列化
在dataclass 数据封装里介绍了,dataclass 数据类型特别适合做接口定义。而且利用 dataclasses.asdict
方法,能够将dataclass转换为常规字典类型,方便json化处理。
例如
@dataclass
class Point:
x: int
y: int
@dataclass
class PointList:
points: List[Point]
在内部使用时,IDE能够为Point类型数据提供类型提示校验。在对外做json转换时,只用对最上层的PointList数据对象做一次 asdict 处理就能方便的完成所有层的 dataclass与字典的转换:
points = PointList(points=[Point(1,0),Point(2,1)])
# 1行代码完成json转换
points_json = json.dumps(asdict(points))
但是,如果dataclass类型中包含枚举型,序列化就会报错:
import json
from dataclasses import dataclass, asdict
from typing import List
from enum import Enum
class Color(Enum):
red = 0
green = 1
blue = 2
@dataclass
class Point:
x: int
y: int
# 增加一个颜色属性,为枚举型
color: Color
@dataclass
class PointList:
points: List[Point]
points = PointList(points=[Point(1, 0, Color.blue), Point(2, 1, Color.red)])
# 1行代码完成json转换
points_json = json.dumps(asdict(points))
print(points_json)
会报出
TypeError: Object of type Color is not JSON serializable
这时候可以这样解决:
from enum import IntEnum
# 用IntEnum代替Enum
class Color(IntEnum):
red = 0
green = 1
blue = 2
也就是说,通过继承IntEnum,Color有了整数类型的序列化方法。
如果枚举值是字符串,看上去对偶的实现方式应该如下:
from enum import StrEnum
class Color(StrEnum):
red = "red"
green = "green"
blue = "blue"
但实际运行中,上述代码会报错,因为 StrEnum 在python 3.11之后才会支持。在低版本中,可以利用多重继承机制,来实现相同功能:
from enum import Enum
class Color(str, Enum):
red = "red"
green = "green"
blue = "blue"
这样,str为Color提供了序列化方法,points整体序列化也能够得到正常的结果:
{"points": [{"x": 1, "y": 0, "color": "blue"}, {"x": 2, "y": 1, "color": "red"}]}
网友评论