[英]Convert dataclass of dataclass to json string
I have a json string that I want to read, convert it to an object that I can manipulate, and then convert it back into a json string.我有一个要读取的 json 字符串,将其转换为我可以操作的 object,然后将其转换回 json 字符串。
I am utilizing the python 3.10 dataclass, and one of the attributes of the class is another class ( mySubClass ).我正在使用 python 3.10 数据类,并且 class 的属性之一是另一个 class ( mySubClass )。 When I call
json.loads(myClass)
, I get the following error: TypeError: Object of type mySubClass is not JSON serializable.
当我调用
json.loads(myClass)
时,我收到以下错误: TypeError: Object of type mySubClass is not JSON serializable.
Is there a way I can instantiate the dataclass myClass with everything it needs (including mySubClass ), and then have a "post init operation" that will convert myClass.mySubClass into a simple json str?有没有办法我可以用它需要的所有东西(包括mySubClass )实例化数据类myClass ,然后有一个“post init 操作”将myClass.mySubClass转换为一个简单的 json str ? Or am I going about this the wrong way?
还是我以错误的方式解决这个问题?
My original goal was to have the following:我最初的目标是拥有以下内容:
import json
from dataclasses import dataclass
@dataclass
mySubClass:
sub_item1: str
sub_item2: str
@dataclass
myClass:
item1: str
item2: mySubClass()
...
convert_new_jsonStr_toObj = json.loads(received_json_str, object_hook=lambda d: SimpleNamespace(**d))
...
#: Get new values/do "stuff" to the received json string
myClass_to_jsonStr = json.dumps(myClass(item1=convert_new_jsonStr_toObj.item1, item2=mySubClass(sub_item1=convert_new_jsonStr_toObj.sub_item1, sub_item2=convert_new_jsonStr_toObj.sub_item2)))
...
#: Final json will look something like:
processed_json_str = "{
"item1" : "new_item1",
"item2" : {
"sub_item1": "new_sub_item1",
"sub_item2": "new_sub_item2"
}"
}
#: send processed_json_str back out...
#: Note: "processed_json_str" has the same structure as "received_json_str".
If I've understood your question correctly, you can do something like this::如果我正确理解了您的问题,您可以执行以下操作::
import json
import dataclasses
@dataclasses.dataclass
class mySubClass:
sub_item1: str
sub_item2: str
@dataclasses.dataclass
class myClass:
item1: str
item2: mySubClass
# We need a __post_init__ method here because otherwise
# item2 will contain a python dictionary, rather than
# an instance of mySubClass.
def __post_init__(self):
self.item2 = mySubClass(**self.item2)
sampleData = '''
{
"item1": "This is a test",
"item2": {
"sub_item1": "foo",
"sub_item2": "bar"
}
}
'''
myvar = myClass(**json.loads(sampleData))
myvar.item2.sub_item1 = 'modified'
print(json.dumps(dataclasses.asdict(myvar)))
Running this produces:运行它会产生:
{"item1": "This is a test", "item2": {"sub_item1": "modified", "sub_item2": "bar"}}
As a side note, this all becomes easier if you use a more fully featured package like pydantic :附带说明一下,如果您使用功能更齐全的 package (如pydantic ),这一切都会变得更容易:
import json
from pydantic import BaseModel
class mySubClass(BaseModel):
sub_item1: str
sub_item2: str
class myClass(BaseModel):
item1: str
item2: mySubClass
sampleData = '''
{
"item1": "This is a test",
"item2": {
"sub_item1": "foo",
"sub_item2": "bar"
}
}
'''
myvar = myClass(**json.loads(sampleData))
myvar.item2.sub_item1 = 'modified'
print(myvar.json())
Without using any libraries other than the builtins:不使用内置函数以外的任何库:
import dataclasses
import json
@dataclasses.dataclass
class mySubClass:
sub_item1: str
sub_item2: str
@dataclasses.dataclass
class myClass:
item1: str
item2: mySubClass
@classmethod
def from_json(cls, string: str):
data: dict = json.loads(string)
if isinstance(data['item2'], dict):
data['item2'] = mySubClass(**data['item2'])
return cls(**data)
def json(self):
return json.dumps(self, default=lambda o: o.__dict__)
sampleData = '''
{
"item1": "This is a test",
"item2": {
"sub_item1": "foo",
"sub_item2": "bar"
}
}
'''
myvar = myClass.from_json(sampleData)
myvar.item2.sub_item1 = 'modified'
print(myvar.json())
Which becomes a bit easier, using a ser/de library like dataclass-wizard
, or dataclasses-json
:使用像
dataclass-wizard
或dataclasses-json
这样的 ser/de 库会变得更容易一些:
import dataclasses
from dataclass_wizard import JSONWizard
@dataclasses.dataclass
class myClass(JSONWizard):
item1: str
item2: 'mySubClass'
# optional
@property
def json(self, indent=None):
return self.to_json(indent=indent)
@dataclasses.dataclass
class mySubClass:
sub_item1: str
sub_item2: str
sampleData = '''
{
"item1": "This is a test",
"item2": {
"sub_item1": "foo",
"sub_item2": "bar"
}
}
'''
c = myClass.from_json(sampleData)
print(c.json)
Disclaimer : I am the creator and maintenor of this library.免责声明:我是这个库的创建者和维护者。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.