Fatal1ty / mashumaro

Fast and well tested serialization library
Apache License 2.0
751 stars 44 forks source link

[BUG] to_msgpack doesn't behave properly with Discriminator(include_subtypes=True) #233

Closed fps7806 closed 1 month ago

fps7806 commented 1 month ago

Description

I was trying to use the msgpack serialization feature with discriminators

What I Did

from dataclasses import KW_ONLY, dataclass, field
from typing import Annotated, Literal

from mashumaro.mixins.msgpack import DataClassMessagePackMixin
from mashumaro.types import Discriminator

@dataclass
class A(DataClassMessagePackMixin):
    _: KW_ONLY
    t: str

@dataclass
class B(A):
    b: list[int]
    _: KW_ONLY
    t: Literal["b"] = "b"

@dataclass
class C(A):
    c: list[int]
    _: KW_ONLY
    t: Literal["c"] = "c"

assert B(b=[]).to_dict() == {"t": "b", "b": []}, B().to_dict()
assert B(b=[1, 2, 3]) == B.from_msgpack(B(b=[1, 2, 3]).to_msgpack())

@dataclass
class Group(DataClassMessagePackMixin):
    group: list[Annotated[A, Discriminator(field="t", include_subtypes=True)]]

assert B(b=[1, 2, 3]) == B.from_msgpack(B(b=[1, 2, 3]).to_msgpack())

g = Group([B(b=[1, 2, 3])])
assert Group.from_dict(g.to_dict()) == g
print(g.to_msgpack())
g2 = Group.from_msgpack(g.to_msgpack())
assert g2 == g, (g2, g)

crashes with:

mashumaro.exceptions.InvalidFieldValue: Field "group" of type list[A] in Group has invalid value [{'t': 'b'}]

because to_msgpack excludes the subtype data:

b'\x81\xa5group\x91\x81\xa1t\xa1b'

using:

@dataclass
class Group(DataClassMessagePackMixin):
    group: list[Annotated[B | C, Discriminator(field="t", include_supertypes=True)]]

works though

Fatal1ty commented 1 month ago

Discriminator is not used on serialization since its purpose is only to select a dataclass on deserialization. However, you are faced with using a parent class serialization issue from #225. I will close this issue as a duplicate, so feel free to subscribe to the related one.