js css html

Python enum 的序列化

2022-10-04  本文已影响0人  alue

枚举型的序列化

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"}]}

上一篇 下一篇

猜你喜欢

热点阅读