将dataclass的dataclass转换为json字符串

Ale*_*lex 5 python oop json class python-dataclasses

我有一个想要读取的 json 字符串,将其转换为我可以操作的对象,然后将其转换回 json 字符串。

我正在使用 python 3.10 数据类,该类的属性之一是另一个类(mySubClass)。当我打电话时 json.loads(myClass),我收到以下错误:TypeError: Object of type mySubClass is not JSON serializable.

有没有办法可以用它需要的一切(包括mySubClass )实例化数据类myClass,然后进行“初始化后操作”,将myClass.mySubClass转换为简单的 json str ?或者我以错误的方式处理这个问题?

我最初的目标是实现以下目标:

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".

Run Code Online (Sandbox Code Playgroud)

lar*_*sks 5

如果我正确理解你的问题,你可以这样做::

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)))
Run Code Online (Sandbox Code Playgroud)

运行此命令会产生:

{"item1": "This is a test", "item2": {"sub_item1": "modified", "sub_item2": "bar"}}
Run Code Online (Sandbox Code Playgroud)

附带说明一下,如果您使用像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())
Run Code Online (Sandbox Code Playgroud)