I have a list of objects in my Python code. Each object is of type Outer with associated Inner objects - the classes are defined like this:
from decimal import Decimal
@dataclass
class Inner:
col_a: Decimal
col_b: str
col_c: List['str']
@dataclass
class Outer:
col_a: str
col_b: Decimal
col_c: List[Inner]
I would like to convert these objects into JSON. As I am using Decimal, I was hoping to just create my own encoder and use it in conjunction with json.dumps():
class DecimalJsonEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Decimal):
return str(obj)
else:
return super(DecimalJsonEncoder, self).default(obj)
... and...
my_json = json.dumps(my_list, cls=DecimalJsonEncoder)
However, when I create a list of Outer objects (my_list) and try to create JSON, I get this error:
TypeError: Object of type Outer is not JSON serializable
I'm using Python 3.7.
Thanks in advance for any assistance.
You wish the encoder to support both Decimal
and dataclass
es. You can do it like so:
import dataclasses, json
class JSONEncoder(json.JSONEncoder):
def default(self, o):
if dataclasses.is_dataclass(o):
return dataclasses.asdict(o)
if isinstance(obj, Decimal):
return str(obj)
return super().default(o)
json.dumps(foo, cls=JSONEncoder)
Just adding an alternate solution that can work for you. This can be especially useful if you need to de-serialize (load) JSON data back to the nested dataclass model.
This uses an external library dataclass-wizard , which is a JSON serialization framework built on top of dataclasses. The example below should work for Python 3.7+ with the included __future__
import.
from __future__ import annotations
from dataclasses import dataclass
from decimal import Decimal
from dataclass_wizard import JSONWizard
@dataclass
class Outer(JSONWizard, str=False):
col_a: str
col_b: Decimal
col_c: list[Inner]
@dataclass
class Inner:
col_a: Decimal
col_b: str
col_c: list[str]
def main():
obj = Outer(col_a='abc',
col_b=Decimal('1.23'),
col_c=[Inner(col_a=Decimal('3.21'),
col_b='xyz',
col_c=['blah', '1111'])])
print(obj)
print(obj.to_json())
# {"colA": "abc", "colB": "1.23", "colC": [{"colA": "3.21", "colB": "xyz", "colC": ["blah", 1111]}]}
# assert we get the same object when de-serializing the string data
assert obj == obj.from_dict(obj.to_dict())
if __name__ == '__main__':
main()
Output:
Outer(col_a='abc', col_b=Decimal('1.23'), col_c=[Inner(col_a=Decimal('3.21'), col_b='xyz', col_c=['blah', '1111'])])
{"colA": "abc", "colB": "1.23", "colC": [{"colA": "3.21", "colB": "xyz", "colC": ["blah", "1111"]}]}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.