lidatong / dataclasses-json

Easily serialize Data Classes to and from JSON
MIT License
1.34k stars 150 forks source link

[BUG] encoders / decoders don't apply to list / dict of the class #512

Open noamgat opened 5 months ago

noamgat commented 5 months ago

Description

Lets say I implemented a custom encoder/decoder for a class, and registered them via cfg.global_config. It works, but it doesn't work if that class is contained in a container (List / Dict).

I think the problem and potential solution (at least for the encoder's site) is in core.py's _asdict(). Shouldn't we check if type(obj) has a custom encoder, and use it if it exists?

Code snippet that reproduces the issue

def test_list_dataclasses_json():
    call_count = 0
    @dataclass_json
    @dataclass
    class Inner:
        inner_val: int

    def encode_inner(inner: Inner):
        nonlocal call_count
        call_count += 1
        return inner.inner_val

    from dataclasses_json import cfg
    cfg.global_config.encoders[Inner] = encode_inner

    @dataclass_json
    @dataclass
    class Outer:
        inner_list: list[Inner]
        inner_instance: Inner

    outer = Outer(inner_list=[Inner(inner_val=1), Inner(inner_val=2)], inner_instance=Inner(inner_val=3))
    outer.to_json()
    assert call_count == 3

Describe the results you expected

I expect the function to be called three times, but it is only called once.

Python version you are using

3.11.6

Environment description

dataclasses_json