pythonpython-decoratorspython-dataclasses

Why can't I override `to_dict` method of a `dataclass` object that uses `dataclasses_json`?


dataclasses_json is a library that provides JSON capabilities to python's data classes. I noticed that overriding to_dict method has no effect. Here's an example:

@dataclass_json
@dataclass
class Message2:
    message: str
    weight: int
    def to_dict(self, encode_json=False):
        print('Custom to_dict')
        ret = {'MESSAGE': self.message, 'WEIGHT': self.weight}
        return ret
m2 = Message2('m2', 2)
print(m2.to_dict())

The code prints the following:

{'message': 'm2', 'weight': 2}

While I was expecting

Custom to_dict
{'MESSAGE': 'm2', 'WEIGHT': 2}

If I remove the @dataclass_json line, I get the desired output.

So, my questions are:

  1. Why defining a function had no effect with @dataclass_json but worked without it?

  2. How can I override to_dict and use @dataclass_json?


Solution

    1. Because dataclass_json simply overrides your to_dict method here:
        cls.to_dict = DataClassJsonMixin.to_dict
    
    1. One possible way is to define a method with different name and after applying dataclass_json decorator use this method to create to_dict method. Complete example with decorator:
    from dataclasses import dataclass
    from dataclasses_json import dataclass_json
    
    
    def recover_to_dict(cls):
        if hasattr(cls, '_to_dict'):
            setattr(cls, 'to_dict', getattr(cls, '_to_dict'))
        return cls
    
    
    @recover_to_dict
    @dataclass_json
    @dataclass
    class Message2:
        message: str
        weight: int
        def _to_dict(self, encode_json=False):
            print('Custom to_dict')
            ret = {'MESSAGE': self.message, 'WEIGHT': self.weight}
            return ret
    m2 = Message2('m2', 2)
    print(m2.to_dict())