Reputation: 1994
I am using marshmallow-dataclass
to build serializable classes, and nest them under another class in a list.
There is a Base
dataclass, which is an abstract class, and has majority of functionality implemented, as well as having @abcmethod
s. From the base, other dataclasses are created; there will be multiple variations, all subclassed from the Base
. Those subclasses work well on their own.
I intend to append all instanced to a Store
dataclass under .items
. Then be able to have it serialized and deserialized.
Below is a simplified version of what I have:
from abc import ABC, abstractmethod
from typing import List, Tuple
import marshmallow_dataclass
from dataclasses import dataclass
@dataclass
class Base(ABC):
name: str
# _klass: str = None
@marshmallow_dataclass.dataclass
class NameAge(Base):
age: int
@marshmallow_dataclass.dataclass
class NameLocation(Base):
loc: Tuple[float, float]
@marshmallow_dataclass.dataclass
class Store:
items: List[Base]
Here is an example of intended use:
a1 = NameAge('John', 33)
a2 = NameLocation('Bob', (50.8, -0.1))
store = Store(items=[a1, a2])
payload = Store.Schema().dump(store)
store_again = Store.Schema().load(payload)
# desired outcome
assert store == store_again
The Problem
Store
instance, the Base
class schema is used for .items
.
The Base
is declared as the type in the List, thus the base is used to build the .Schema()
as the serializer.
However, the desired behaviour is for each instance to be (de-)serialzed its dedicated class.What I tried so far
_klass
to serialize and track which class is used, so the right serializer can be built.@marshmallow_dataclass.dataclass(base_schema=BaseSchema)
), trying to intercept with @pre_dump
and @pre_load
, but without much success.Base.__new__
in order to return the right schema class, however it seemed it was not called at deserialization stage.Any suggestions or help will be much appreciated.
Upvotes: 0
Views: 1895
Reputation: 855
Schemas are not inherited: how would the deserialisation know about a class's child classes? Instead use typing.Union
:
from abc import ABC, abstractmethod
from typing import List, Tuple, Union
...
@marshmallow_dataclass.dataclass
class Store:
items: List[Union[NameAge, NameLocation]]
You'll need to install the union
extra: pip install marchmallow-dataclass[union]
Upvotes: 1