Make the Python json encoder support Pythons new dataclasses

Make the Python json encoder support Pythons 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, json

class 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)

Cant you just use the dataclasses.asdict() function to convert the dataclass
to a dict? Something like:

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

Make the Python json encoder support Pythons new dataclasses

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 dataclasses
import json


@dataclass.dataclass
class Foo:
    x: str

foo = Foo(x=1)
json_foo = json.dumps(dataclasses.asdict(foo)) # {x: 1}

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

Marshmallow Dataclass

from dataclasses import field
from marshmallow_dataclass import dataclass


@dataclass
class 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 dataclass
from dataclasses_json import dataclass_json


@dataclass_json
@dataclass
class Foo:
    x: int

foo = Foo(x=1)
json_foo = foo.to_json() # Foo(x=1)
# Back to class instance
Foo.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.

Leave a Reply

Your email address will not be published. Required fields are marked *