我正在做一个项目,学习更多关于使用Python dataclasses的知识。具体地说,我试图将API响应表示为dataclass对象。然而,由于API响应的结构,我遇到了一个问题。
以下是来自API的示例响应:
{
"@identifier": "example",
"@name": "John Doe",
}某些字段的名称中包含特殊字符。这意味着我不能直接映射我的dataclass的属性,因为属性名(SyntaxError)中不允许使用诸如@之类的特殊字符。
有没有办法为我的API属性定义一个别名,这样我就可以将dataclass响应直接映射到dataclass对象?还是有必要先清理响应?
发布于 2021-04-08 18:11:51
有一个dataclasses-json,它允许您为属性设置别名:
from dataclasses import dataclass, field
from dataclasses_json import config, dataclass_json
@dataclass_json
@dataclass
class Person:
magic_name: str = field(metadata=config(field_name="@name"))
magic_id: str = field(metadata=config(field_name="@identifier"))
p = Person.from_json('{"@name": "John Doe", "@identifier": "example"}')
print(p.magic_name)
print(p.to_json())输出:
John Doe
{"@name": "John Doe", "@identifier": "example"}发布于 2021-04-08 18:02:06
事实是,不仅对象的属性的名称中不能有特殊字符,变量也不能。在Python中,变量名中只允许使用字符a-z、A-Z、0-9和_,如果您尝试这样做(v@r = 3),如您所说,您将得到SyntaxError。另请注意,变量名中允许使用数字,但变量开头不允许使用数字:
# Ok
test0 = 'Hello World!'
# SyntaxError
0test = 'Goodbye Moonman!'我建议更改属性的名称,从您的dict键中删除特殊字符,如@。因为最后,您需要在属性名称中添加特殊字符的目的是什么?
也许你可以使用Python object的__getitem__和__setitem__魔法方法来解决这个问题:
class Object():
def __init__(self, props):
self._props = props
def __getitem__(self, i):
return self._props[i]因此,您现在可以使用以下内容:
x = {'Hello': 'World!', '@oodby&': 'Moonman!'}
x = Object(x)
print(x['Hello']) # World!
print(x['@oodby&']) # Moonman!也许这并不完全是你想要的,尽管这可能有它的优点。例如,您可以定义一些类方法来处理self._props。
有关__getitem__ here的更多信息:)
发布于 2021-04-08 18:31:26
添加一个'clean‘函数,并用它包装API响应字典。
该解决方案不需要外部库。
from dataclasses import dataclass
api_response = {
"@identifier": "example",
"@name": "John Doe",
}
def clean(data: dict) -> dict:
def _clean(key):
return key[1:]
result = {}
for k, v in data.items():
result[_clean(k)] = v
return result
@dataclass
class Response:
name: str
identifier: str
res = Response(**clean(api_response))
print(res)输出
Response(name='John Doe', identifier='example')https://stackoverflow.com/questions/67001442
复制相似问题