Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Custom Serializer doesn't work with top-level data. #514

Open
Jasha10 opened this issue Apr 18, 2024 · 0 comments
Open

Custom Serializer doesn't work with top-level data. #514

Jasha10 opened this issue Apr 18, 2024 · 0 comments
Labels
bug Bug report or fix

Comments

@Jasha10
Copy link

Jasha10 commented Apr 18, 2024

It seems that custom serializers don't work if the custom data type is at the top level.

For example, suppose I implement a custom serializer for MyClass, and I wrap MyClass inside a dataclass MyWrapper.

When I call serde.to_dict(MyWrapper(MyClass(...))), the custom serializer for MyClass works as expected.
When I call serde.to_dict(MyClass(...)), however, the custom serializer is not used.

This is unexpected; I would expect serde.to_dict(MyClass(...)) to invoke the custom serializer too.

In the below example, the second assertion fails.

# serde_partial.py

from plum import dispatch
import serde
from typing import Any
from dataclasses import dataclass


Type = type  # You should prefer to use type[...] instead of Type[...]!


class MyClass:
    def __init__(self, a, b):
        self.a = a
        self.b = b
    def __eq__(self, other):
        return self.a == other.a and self.b == other.b

class MySerializer:
    @dispatch
    def serialize(self, value: MyClass) -> dict[str, Any]:
        return {'a': value.a, 'b': value.b}

class MyDeserializer:
    @dispatch
    def deserialize(self, cls: Type[MyClass], value: dict[str, Any]) -> MyClass:
        return MyClass(value['a'], value['b'])


serde.add_serializer(MySerializer())
serde.add_deserializer(MyDeserializer())

@dataclass
class MyWrapper:
    value: MyClass

# When MyClass is wrapped inside a dataclass, to_dict and from_dict work correctly
obj = MyWrapper(MyClass(1, 2))
expected = {'value': {'a': 1, 'b': 2}}
result = serde.to_dict(obj)
assert isinstance(result, dict)
assert result == expected
assert serde.from_dict(MyWrapper, result) == obj

# When MyClass is not wrapped inside a dataclass, to_dict fails to serialize it
obj = MyClass(1, 2)
expected = {'a': 1, 'b': 2}
result = serde.to_dict(obj)
assert isinstance(result, dict), f"Expected dict, got {type(result)}"  # ASSERTION FAILS
$ python serde_partial.py
Traceback (most recent call last):
  File "/home/homestar/tmp/serde_partial.py", line 49, in <module>
    assert isinstance(result, dict), f"Expected dict, got {type(result)}"  # ASSERTION FAILS
AssertionError: Expected dict, got <class '__main__.MyClass'>
@yukinarit yukinarit added the bug Bug report or fix label Apr 28, 2024
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug Bug report or fix
Projects
None yet
Development

No branches or pull requests

2 participants