前言
之前接到过这样一个需求,从后台某个接口获取配置,配置数据按json格式返回,类似这样:
代码语言:json复制{
"data":{
"id":1,
"min":30,
"max":100
}
}
从配置里面取数据很简单嘛,把json转成dict,直接data["字段名"]
就可以取数据,为了规范化,方便以后随时能知道接口有哪些字段,我使用了dataclass来定义,并用dacite库加载数据类
定义dataclass
代码语言:python代码运行次数:0复制from dataclasses import dataclass
import dacite
@dataclass
class Config:
id: int
min: int
max: int
data = {
"id": 1,
"min": 30,
"max": 100
}
data = dacite.from_dict(data_class=Config, data=data)
print(data.id, data.min, data.max)
遇到问题
以上代码是ok的,但是哪知道同事给我返回数据时,json里面没有返回int类型,全是字符串类型,而且字符串还带浮点,类似这样:
代码语言:json复制{
"data" = {
"id": "1.00",
"min": "30.00",
"max": "100.00"
}
}
这时加载的代码就出错了,会报WrongTypeError,因为定义的是int类型,而字段实际数据是str类型。我只能把dataclass的定义全改成str类型,定义如下:
代码语言:python代码运行次数:0复制@dataclass
class Config:
id: str
min: str
max: str
可这样也太麻烦了吧,我每次用这个字段,还是要当成int型来用,所以只能这样转:
代码语言:python代码运行次数:0复制min = "30.00"
min = int(float(min))
一个配置里面有几十个字段,每个字段用到的地方都很多,代码里全是类型转换,心累。
解决问题
看了一下dacite库的源码,直接当标注类型和数据类型不一致时,强制转换类型,这样就可以把数据标注成自己想要的类型,且自动实现强制转换了,代码如下:
代码语言:python代码运行次数:0复制from typing import Type, Any
import dacite
from dacite import Config
from dacite.core import _build_value
def __build_type(type_: Type, data: Any, config: Config):
new_data = _build_value(type_=type_, data=data, config=config)
# 当标注类型和实际数据类型不一致时,进行类型转换
if not isinstance(new_data, type_):
# 如果标注类型是int,实际数据是str,且数据是浮点数,转换为整数
if type_.__name__ == "int" and isinstance(new_data, str):
new_data = int(float(new_data))
new_data = type_(new_data)
return new_data
dacite.core._build_value = __build_type
总结
成功通过替换dacite的函数,实现了类型强制转换的效果,舒服了n_n