使用getter-setter创建类,该类使用python3从json获取数据



我正在为第三方应用程序使用RESTAPI构建一个应用程序。当我从API检索对象时,它会向我发送一个json,我将其传递到一个类中,该类内部取出密钥,并通过使用property的类提供数据

示例:

有效载荷:

{
"value":{
"boot":{
"delay":10,
"legacy_boot":false
}
}
}
class AbstractInfo:
def __init__(self, json):
try:
self.info = json["value"]
except KeyError:
# KeyError is raised when nested dictionary is passed which does not contain `value` key
self.info = json
def to_dict(self):
return self.info
class BootInfo(AbstractInfo):
@property
def delay(self):
return self.info["delay"]
@property
def legacy_boot(self):
return self.info["legacy_boot"]
class MainInfo(AbstractInfo):
@property
def boot(self):
return BootInfo(json=self.info["boot"])

现在,从其他一些过程中,我使用动态导入调用MainInfo类,并执行类似的操作

# Do rest API call and get the payload in a variable
MainInfo(json=payload)

到目前为止,这一切都很好,我只是想从有效载荷中获取值,就像一样

# GetInfo does dynamic import for the correct class based on the resource_id
info = GetInfo("resource_id")
print(info.boot.delay)

现在,我的目标是使用BootInfo中定义的模式创建一个对象,以便它返回相关的dictionary

以下是打印报表的结果,有助于清理

print(MainInfo(json=json).to_dict())
{'boot': {'delay': 10, 'legacy_boot': False}}
print(MainInfo(json=json).boot.to_dict())
{'delay': 10, 'legacy_boot': False}

我想做一些类似的事情

bi = BootInfo(delay=20, legacy_boot=True).build_dict()
print(bi)
{'delay': 20, 'legacy_boot': True}
# Then use `bi` into another place to mount the dictionary easily like building a lego set

我知道我的BootInfo不接受delaylegacy_boot作为自变量。如果我添加它们,那么当数据通过json到达时,我如何设置值?我觉得我在这里处境艰难。如果可能的话,我希望保持代码的当前结构不变,这样从嵌套结构中查找键的工作量就会减少。我的嵌套结构越多,我生成的类就越多。当某个键依赖于另一个属性的值并且可能在json负载中不可用时,我还在属性下进行验证。

我研究了gettersetter,尝试了一些事情,遇到了一些问题,但无法满足我的需求。

有人知道完成这项工作的最佳方法吗?或者用示例代码向我展示正确的方向吗?

我认为这是关于何时使用验证器库的一个主要示例。(个人最爱:https://pydantic-docs.helpmanual.io/)

优点:

  1. 您可以通过强类型预期的json和嵌套结构来验证通过API获取的数据
  2. 它拥有将dict转换为class和将class转换为dict的所有helper方法,以及在必要时读取json字符串的方法

示例:

from pydantic import BaseModel
class BootInfo(BaseModel):
delay: int
legacy_boot: bool
class MainInfo(BaseModel):
boot: BootInfo

class Info(BaseModel):
value: MainInfo

那么你可以做:

payload = {
"value":{
"boot":{
"delay":10,
"legacy_boot":false
}
}
}
info = Info(**data)
info.value.boot.delay
info.value.boot.legacy_boot
assert info.dict() == payload
# or init the class by properties
boot_info = BootInfo(delay=10, legacy_boot=False)
assert boot_info.delay == 10
boot_info.dict()

最新更新