Open othmane099 opened 5 months ago
@othmane099 This is the expected behavior. You have to set a different dacite config
By adding the following dacite_config
settings to CoreMessage
:
@dataclass
class CoreMessage(AvroModel):
messageBody: typing.Union[
MessageTypeOne,
MessageTypeTwo,
]
class Meta:
dacite_config = {
"strict_unions_match": True,
"strict": True,
}
The previous example (MessageTypeTwo
) works as expected. However, in the case of MessageTypeOne
:
mt1 = MessageTypeOne()
core_message = CoreMessage(messageBody=mt1)
serialized = core_message.serialize()
deserialized = CoreMessage.deserialize(serialized)
print(deserialized.messageBody)
an exception dacite.exceptions.StrictUnionMatchError: can not choose between possible Union matches for field "messageBody": MessageTypeOne, MessageTypeTwo
Could the issue be attributed to the absence of fields within the MessageTypeOne
class?
Not really. In your case if you use the following config it should work
class Meta:
dacite_config = {
"strict": True,
}
In any case, sometimes it is not possible to cover all cases so you will have to play with differentt dacite config
Thanks for your answer. I encountered another case where the types have same attribute name, for example:
from dataclasses_avroschema import AvroModel
from dataclasses import dataclass
import typing
@dataclass
class MessageTypeTwo(AvroModel):
val: str
class Meta:
namespace = "Messages.type.two"
@dataclass
class MessageTypeOne(AvroModel):
val: str
class Meta:
namespace = "Messages.type.one"
@dataclass
class CoreMessage(AvroModel):
messageBody: typing.Union[
MessageTypeOne,
MessageTypeTwo,
]
class Meta:
dacite_config = {
"strict": True,
}
mt2 = MessageTypeTwo("Hello World")
core_message = CoreMessage(messageBody=mt2)
serialized = core_message.serialize()
deserialized = CoreMessage.deserialize(serialized)
print(deserialized.messageBody)
Expected: MessageTypeTwo(val='Hello World')
Actual: MessageTypeOne(val='Hello World')
Yes, it makes sense. It is impossible to determine which class should be created. Under the hood you get a json
{"messageBody": {"val": "Hello World"}}
and it is impossible to know which class to use. You must define a different strategy or include extra data to distinguish among the objects.
I encountered an issue while using the dataclasses-avroschema package for Avro serialization in Python. When attempting to serialize and deserialize a dataclass with a union type using dataclasses_avroschema, the deserialized object doesn't match the expected type.
Serialize and deserialize an instance of CoreMessage with an instance of MessageTypeTwo:
Expected Result: The print statement should output MessageTypeTwo(val='val').
Actual Result: The print statement outputs MessageTypeOne().