-
-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Discriminator
not respected by JSONEncoder
when it works for to_json
.
#239
Comments
JSONEncoder
/JSONDecoder
behavior differs with to_json
/from_json
.
flyteorg/flyte#5588
@Fatal1ty, can you take a look? |
@Future-Outlier Sorry for taking so long. I'll try to find time soon to dive into the problem. At first glance it looks similar to #225 |
No problem, thank you so much! |
@Fatal1ty I see how this is related to #225, do you have a pointer to the optimization you made and mention there? Happy to help digging + ideating from there. The example you provided is at least somewhat different as in this case it's possible to tell from |
@JackUrb Just to be clear, the discriminator is not and was never intended to be used as additional information for serialization (encoding) process. Its only purpose is to create conditions for selecting a class when decoding from raw data, because we have nothing but the data. When you have a dataclass instance, you can tell which dataclass it belongs to and theoretically this information can be useful on encoding. However, this is not happening in your case when a separate @dataclass(kw_only=True)
class BaseClass(DataClassJSONMixin):
class Config(BaseConfig):
discriminator = Discriminator(
field="subclass_type",
include_subtypes=True,
)
subclass_type: SubclassTypes = SubclassTypes.BASE
base_attribute: int
encoder = JSONEncoder(BaseClass)
@dataclass(kw_only=True)
class ClassA(BaseClass):
subclass_type: SubclassTypes = SubclassTypes.CLASS_A
class_a_attribute: str
class_a = ClassA(base_attribute=1, class_a_attribute="a")
encoder.encode(class_a) I moved definition of On the other hand, using And now we are coming to the point of figuring out what to do in this situation. The good news is that it looks like in your case you intend to combine the mixins and the encoders together. In such a case, you can use the dialect to customize the serialization of the from dataclasses import dataclass
from mashumaro.dialect import Dialect
from mashumaro.mixins.json import DataClassJSONMixin
from mashumaro.codecs.json import JSONEncoder
from mashumaro.config import BaseConfig
from mashumaro.types import Discriminator
from enum import StrEnum, auto
class SubclassTypes(StrEnum):
BASE = auto()
CLASS_A = auto()
CLASS_B = auto()
@dataclass(kw_only=True)
class BaseClass(DataClassJSONMixin):
class Config(BaseConfig):
discriminator = Discriminator(
field="subclass_type",
include_subtypes=True,
)
subclass_type: SubclassTypes = SubclassTypes.BASE
base_attribute: int
@dataclass(kw_only=True)
class ClassA(BaseClass):
subclass_type: SubclassTypes = SubclassTypes.CLASS_A
class_a_attribute: str
@dataclass(kw_only=True)
class ClassB(BaseClass):
subclass_type: SubclassTypes = SubclassTypes.CLASS_B
class_b_attribute: float
class BaseClassDialect(Dialect):
serialization_strategy = {BaseClass: {"serialize": lambda x: x.to_dict()}}
base_class_encoder = JSONEncoder(BaseClass, default_dialect=BaseClassDialect)
class_a = ClassA(base_attribute=1, class_a_attribute="a")
class_b = ClassB(base_attribute=2, class_b_attribute=2.0)
print(class_a.to_json())
print(base_class_encoder.encode(class_a))
print(class_b.to_json())
print(base_class_encoder.encode(class_b)) Please let me know if this works for you. |
Hi @Fatal1ty, thanks for digging into this and explaining upfront your intent on building these encoders. Your first example captures the issue fairly well, as it'd be somewhat unreasonable to crawl for things that haven't necessarily been defined. Short of a registry pattern inside of the discriminator that explicitly points out the target subclasses (which I think would be somewhat unwieldy), there's no clear way to do this at creation-time of the encoder. For the use case within |
Description
Thanks for the library! It enables some really cool functionality that I've become a fan of.
Unfortunately, as discovered in flyteorg/flyte#5588, it was surprising to find that the behavior differs between the use of
mashumaro
'sJSONEncoder
and theto_json
method of a class extendingDataclassJSONMixin
.JSONEncoder
does not appear to respect anyDiscriminator
configuration, preventing correct serialization/deserialization when usingJSONEncoder
for this purpose on classes that use theDiscriminator
pattern.Is this to be expected that
JSONEncoder
(and likely decoder) supports a subset of the features thatto_json
does?What I Did
I would expect these to be equivalent, but they are not:
The text was updated successfully, but these errors were encountered: