Make the Python json encoder support Python's new dataclasses Make the Python json encoder support Python's new dataclasses python python

Make the Python json encoder support Python's new dataclasses


Much like you can add support to the JSON encoder for datetime objects or Decimals, you can also provide a custom encoder subclass to serialize dataclasses:

import dataclasses, jsonclass EnhancedJSONEncoder(json.JSONEncoder):        def default(self, o):            if dataclasses.is_dataclass(o):                return dataclasses.asdict(o)            return super().default(o)json.dumps(foo, cls=EnhancedJSONEncoder)


Can't you just use the dataclasses.asdict() function to convert the dataclassto a dict? Something like:

>>> @dataclass... class Foo:...     a: int...     b: int...     >>> x = Foo(1,2)>>> json.dumps(dataclasses.asdict(x))'{"a": 1, "b": 2}'


Ways of getting JSONified dataclass instance

There are couple of options to accomplish that goal, selection of each imply analyze on which approach suits best for your needs:

Standart library: dataclass.asdict

import dataclassesimport json@dataclass.dataclassclass Foo:    x: strfoo = Foo(x='1')json_foo = json.dumps(dataclasses.asdict(foo)) # '{"x": "1"}'

Picking it back to dataclass instance isn't trivial, so you may want to visit that answer https://stackoverflow.com/a/53498623/2067976

Marshmallow Dataclass

from dataclasses import fieldfrom marshmallow_dataclass import dataclass@dataclassclass Foo:    x: int = field(metadata={"required": True})foo = Foo(x='1') # Foo(x='1')json_foo = foo.Schema().dumps(foo) # '{"x": "1"}'# Back to class instance.Foo.Schema().loads(json_foo) # Foo(x=1)

As a bonus for marshmallow_dataclass you may use validation on the field itself, that validation will be used when someone deserialize the object from json using that schema.

Dataclasses Json

from dataclasses import dataclassfrom dataclasses_json import dataclass_json@dataclass_json@dataclassclass Foo:    x: intfoo = Foo(x='1')json_foo = foo.to_json() # Foo(x='1')# Back to class instanceFoo.from_json(json_foo) # Foo(x='1')

Also, in addition to that notice that marshmallow dataclass did type conversion for you whereas dataclassses-json(ver.: 0.5.1) ignores that.

Write Custom Encoder

Follow accepted miracle2k answer and reuse custom json encoder.