dataclass转换为具有特定变量名的json



我有一个数据结构,我想把它变成json。这里是我的课程:

@dataclass
class RType:
type_name: str
class Meta:
name = '@r_type'
content = 'type_name'

@dataclass
class Options:
type: RType
content: str
class Meta:
name = 'options'
content = 'content'

我想从结果中得到什么(我们总是在嵌套和正常结构中有r_type(:

{
'@r_type' : 'init',
'options': {
'@r_type' : 'options',
'options' : 'some_options'
}

的另一个例子

{
'@r_type' : 'dir_init',
'directory': {
'@r_type' : 'directory',
'directory' : 'path_to'
}

问题是,我们可以使用addict或库轻松地将常规类转换为json,但我的变量名包含'@'

我该怎么做?(理想情况下不使用库(

这会以一种基本合理的方式满足您的要求。我对您的结构的问题是RType不是对象类型。这只是你其他类型的一个属性。

对我的原始脚本的修改添加了一个函数,将r_types值移动到每个dict的前面。这不是一个完全通用的解决方案;如果列表中嵌套了列表,则需要对其进行更改。事实上,它可以与dict或包含dict的列表一起使用。

但是您的JSON阅读器有缺陷。你应该提交一份错误报告。

from dataclasses import dataclass, asdict
import json
@dataclass
class Options:
options: str
r_type: str = "options"
@dataclass
class Init:
options: Options
r_type: str = "init"
def movetypes(dct):
newdct = {}
if 'r_type' in dct:
newdct['@r_type'] = dct['r_type']
for key,value in dct.items():
if key == 'r_type':
continue
if isinstance(value,dict):
value = movetypes(value)
elif isinstance(value,list):
value = [movetypes(v) for v in value]
newdct[key] = value
return newdct
x = Options('some_options')
y = Init([x])
dct = asdict(y)
print(dct)
dct = movetypes(dct)
print(dct)
js = json.dumps(dct)
print(js)

输出:

{'options': [{'options': 'some_options', 'r_type': 'options'}], 'r_type': 'init'}
{'@r_type': 'init', 'options': [{'@r_type': 'options', 'options': 'some_options'}]}
{"@r_type": "init", "options": [{"@r_type": "options", "options": "some_options"}]}

我知道你要求一个没有库的解决方案,但这里有一个干净的方法,至少在我看来是Python的。这确实利用了一个外部库dataclass-wizardjson_fielddataclasses.field的同义用法,但指定了用于(反(序列化的别名。

另外请注意:我需要交换字段的顺序,因此需要将options字段声明为可选字段。由于字典顺序应该是定义数据类字段的顺序,这确保了@r_type在序列化的dict结果中首先显示。

from __future__ import annotations  # note: can be removed in Python 3.10
import json
from dataclasses import dataclass
from dataclass_wizard import asdict, json_field

@dataclass
class Init:
r_type: str = json_field('@r_type', all=True, default='init')
options: Options | None = None

@dataclass
class Options:
r_type: str = json_field('@r_type', all=True, default='options')
options: str | None = None

x = Options(options='some_options')
y = Init(options=[x])
dct = asdict(y)
# print(dct)
# {'@r_type': 'init', 'options': [{'@r_type': 'options', 'options': 'some_options'}]}
print(json.dumps(dct, indent=2))

输出:

{
"@r_type": "init",
"options": [
{
"@r_type": "options",
"options": "some_options"
}
]
}

最新更新