美文网首页
字典转dataclass

字典转dataclass

作者: alue | 来源:发表于2022-10-05 15:36 被阅读0次

输入接口的数据往往是json格式,一般通过 json.loads() 将其转换为字典类型。为了便于内部使用,往往用 dataclass 封装这个字典。

这个过程有时候很简单

@dataclass
class Point:
     x: int
     y: int


p = {"x": 1, "y": 0}

# 利用**完成参数输入
Point(**p)

如果带有枚举等特殊字段,就需要对字段做特殊处理

from dataclasses import dataclass  
from enum import Enum  
  
  
class Color(Enum):  
    red = 0  
    green = 1  
    blue = 2  
  
  
@dataclass  
class Point:  
    x: int  
    y: int  
    # 增加一个颜色属性,为枚举型  
    color: Color  
  
  
p = {"x": 1, "y": 0, "color": 1}  

# 这样会出问题
point1 = Point(**p)  
# False
print(point1.color == Color.green)  

# 这样可行
point2 = Point(**dict(p, color=Color(p['color'])))  
# True
print(point2.color == Color.green)


如果dataclass有嵌套的情况,那么处理起来更加麻烦

@dataclass  
class Line:  
    p1: Point  
    p2: Point  
    color: Color  
  
  
line = {  
    "p1": {"x": 1, "y": 0, "color": 1},  
    "p2": {"x": 1, "y": 0, "color": 1},  
    "color": 2,  
  
}  

# 这样处理不行
l1 = Line(**line)  
# 'dict' object has no attribute 'color'
print(l1.p1.color)

# 必须这样处理

l0 = Line(  
    p1=Point(**dict(line["p1"], color=Color(line["p1"]['color']))),  
    p2=Point(**dict(line["p2"], color=Color(line["p2"]['color']))),  
    color=Color(line['color'])  
)  
# Color.green
print(l0.p1.color)

这里提供一个解决方案 —— 利用 dacite 库 , 只用一行就能够实现上面繁琐的赋值过程:

from dacite import from_dict, Config
l2 = from_dict(Line, line, Config(cast=[Enum]))  
print(l2)


"""
Line(p1=Point(x=1, y=0, color=<Color.green: 1>), p2=Point(x=1, y=0, color=<Color.green: 1>), color=<Color.blue: 2>)
"""

相关文章

网友评论

      本文标题:字典转dataclass

      本文链接:https://www.haomeiwen.com/subject/nfrpartx.html