Skip to content

[BUG] Extending de/encoders do not work with from __future__ import annotations #547

@orilg

Description

@orilg

Description

Writing my own class to be used as a dataclass field, I extend the json encoder / decoder with dataclasses_json.cfg.global_config.encoders/decoders.
When adding from __future__ import annotations the type turns to str and the encoder / decoder I've added to cfg does not automatically detect it as that type.

workaround : adding the same encoder/decoder to cfg with key cls.name in addition to cls

Code snippet that reproduces the issue

from __future__ import annotations
from typing import Any
from dataclasses import dataclass
from dataclasses_json import DataClassJsonMixin, cfg


class MyNestedClass:
    def __init__(self, my_str: str, my_int: int =1) -> None:
        self._my_str = my_str
        self._my_int = my_int

    def __eq__(self, other: Any) -> bool:
        if not isinstance(other, MyNestedClass):
            return False
        return (self._my_str, self._my_int) == (other._my_str, self._my_int)

    def to_dict(self) -> dict[str,str]:
        return {"my_str" : self._my_str}

    @classmethod
    def from_dict(cls, asdict:dict[str,str]) -> "MyNestedClass":
        return MyNestedClass(my_str=asdict['my_str'])

cfg.global_config.encoders[MyNestedClass] = MyNestedClass.to_dict
cfg.global_config.decoders[MyNestedClass] = MyNestedClass.from_dict

@dataclass
class MyClass(DataClassJsonMixin):
    my_nested_inst: MyNestedClass

class_with_nested = MyClass(MyNestedClass('asdf'))
print(f"class_with_nested : {class_with_nested}")
print(f"MyClass.from_json(class_with_nested.to_json()) : {MyClass.from_json(class_with_nested.to_json())}")
assert class_with_nested ==  MyClass.from_json(class_with_nested.to_json())

This is what I get

class_with_nested : MyClass(my_nested_inst=<__main__.MyNestedClass object at 0x7982297b8810>)
MyClass.from_json(class_with_nested.to_json()) : MyClass(my_nested_inst={'my_str': 'asdf'})
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[1], line 33
     31 print(f"class_with_nested : {class_with_nested}")
     32 print(f"MyClass.from_json(class_with_nested.to_json()) : {MyClass.from_json(class_with_nested.to_json())}")
---> 33 assert class_with_nested ==  MyClass.from_json(class_with_nested.to_json())

AssertionError:

Describe the results you expected

class_with_nested : MyClass(my_nested_inst=<__main__.MyNestedClass object at 0x7982297b8810>)

MyClass.from_json(class_with_nested.to_json()) : MyClass(my_nested_inst==<__main__.MyNestedClass object at 0xXXXXX>)

# No assertion : class_with_nested ==  MyClass.from_json(class_with_nested.to_json()) is True

Python version you are using

3.11.4

Environment description

asttokens==2.4.1
dataclasses-json==0.6.7
decorator==5.1.1
executing==2.1.0
ipython==8.27.0
jedi==0.19.1
marshmallow==3.22.0
matplotlib-inline==0.1.7
mypy-extensions==1.0.0
packaging==24.1
parso==0.8.4
pexpect==4.9.0
prompt_toolkit==3.0.48
ptyprocess==0.7.0
pure_eval==0.2.3
Pygments==2.18.0
six==1.16.0
stack-data==0.6.3
traitlets==5.14.3
typing-inspect==0.9.0
typing_extensions==4.12.2
wcwidth==0.2.13

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions