dataclasses-json icon indicating copy to clipboard operation
dataclasses-json copied to clipboard

[FEATURE] ADT Support

Open IlyaHalsky opened this issue 7 months ago • 0 comments

Description

I'm not sure if this is even possible: I want to create summ type of dataclasses, which can be distinguished by some field:

class Base(DataClassJsonMixin):
    tpe: str

@dataclass_json
@dataclass
class A(Base):
    field1: int
    tpe: str = 'a'

@dataclass_json
@dataclass
class B(Base):
    field2: str
    tpe: str = 'b'

So that Base.from_json("""{"field1": 1, "tpe": "a"}""") would produce A(1, 'a').

Possible solution

Some kind of annotation for base class where I can register child types so it can handle from_dict and from_json

Alternatives

Scala's library Circe can do it by registering all classes in summ type or by pointing to the discriminator field circe-adt.

My current workaround looks like this:

all_types = [A,B]

class BaseDecoder:
    types_map = {}
    for type_instance in all_types:
        types_map[type_instance.tpe] = type_instance

    @staticmethod
    def decode_dict(object_dict: dict) -> Base | None:
        if 'tpe' in object_dict and object_dict['tpe'] in BaseDecoder.types_map:
            decoder = BaseDecoder.types_map[object_dict['tpe']]
            return decoder.from_dict(object_dict)
        else:
            raise Exception(f"Unknown type {object_dict}")

@dataclass_json
@dataclass
class Wrapper:
    value: Base = field(metadata=config(decoder=BaseDecoder.decode_dict))

Context

No response

IlyaHalsky avatar Jul 24 '24 12:07 IlyaHalsky