Closed GuillaumeDesforges closed 1 year ago
Hmm...
I'm not sure that is the pydantic-xml
bug.
The following pure pydantic
code behave the same way:
>>> from typing import Union
>>> from pydantic import BaseModel
>>>
>>>
>>> class SubModel1(BaseModel):
... text: str
...
>>>
>>> class SubModel2(BaseModel):
... text: str
...
>>>
>>> class TestModel(BaseModel):
... field1: Union[SubModel1, SubModel2]
...
>>>
>>> obj = TestModel.parse_obj({'field1': SubModel2(text='foo')})
>>> print(obj)
field1=SubModel1(text='foo')
I think the problem is that parse_obj
transforms the object to a dict before parsing. Since SubModel1
and SubModel2
have the same signature, union choose the first model matched which is SubModel1
.
Thanks for the reply.
My issue is not about the deserialization but the serialization.
The error in my test does not fail when parsing XML My test fails when trying to serialize
actual_xml = actual_obj.to_xml()
> assert_xml_equal(actual_xml, xml)
Does to_xml
rely on parse_obj
?
The error in my test does not fail when parsing XML. My test fails when trying to serialize
Yes, I understand that
Does to_xml rely on parse_obj?
Yes, in context of Union
type the decision which deserializer to use is based on the actual field type, which in turn derived using pydantic parse_obj
. So if pydantic choose a wrong field type on serialization, a wrong deserializer is chosen on deserialization.
@GuillaumeDesforges found the solution.
Switch on smart_union
flag for your model:
class TestModel(BaseXmlModel, tag='model'):
class Config:
smart_union = True
field1: Union[SubModel1, SubModel2] = element()
Thanks a lot, that's very helpful!
If a root model has a field of type the union of two models which are similar, the serializer will pick the first one in the union.
I've implemented this test https://github.com/GuillaumeDesforges/pydantic-xml/commit/f36068168f890bb50efdeaa3565f1659bd00450d
Which raises