From 8512afc0a87053dbde52af0519c74198fa3bb873 Mon Sep 17 00:00:00 2001 From: Tristan Cartledge <108070248+TristanSpeakEasy@users.noreply.github.com> Date: Thu, 1 Feb 2024 20:26:55 +0000 Subject: [PATCH] fix: deserialization of unions if the type of a field with the same name differs between union members (#511) --- dataclasses_json/core.py | 2 +- tests/test_union.py | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/dataclasses_json/core.py b/dataclasses_json/core.py index d1a75aae..bf7b7cc8 100644 --- a/dataclasses_json/core.py +++ b/dataclasses_json/core.py @@ -320,7 +320,7 @@ def _decode_generic(type_, value, infer_missing): try: res = _decode_dataclass(type_option, value, infer_missing) break - except (KeyError, ValueError): + except (KeyError, ValueError, AttributeError): continue if res == value: warnings.warn( diff --git a/tests/test_union.py b/tests/test_union.py index 57b848b9..a8dce016 100644 --- a/tests/test_union.py +++ b/tests/test_union.py @@ -42,11 +42,13 @@ class Aux2: class Aux3: f2: str + @dataclass_json @dataclass class C4: f1: Union[Aux1, Aux2] + @dataclass_json @dataclass class C12: @@ -124,6 +126,31 @@ class C11: """ f1: Union[str, None] = None + +@dataclass_json +@dataclass +class C13: + data: str + + +@dataclass_json +@dataclass +class C14: + content: str + + +@dataclass_json +@dataclass +class C15: + data: C13 + + +@dataclass_json +@dataclass +class C16: + event: Union[C15, C13] + + params = [ (C1(f1=12), {"f1": 12}, '{"f1": 12}'), (C1(f1="str1"), {"f1": "str1"}, '{"f1": "str1"}'), @@ -209,6 +236,7 @@ def test_deserialize_with_error(cls, data): with pytest.raises(ValidationError): assert s.load(data) + def test_deserialize_without_discriminator(): # determine based on type json = '{"f1": {"f1": 1}}' @@ -239,4 +267,12 @@ def test_deserialize_without_discriminator(): json = '{"f1": {"f3": "str2"}}' s = C12.schema() obj = s.loads(json) - assert type(obj.f1) == dict \ No newline at end of file + assert type(obj.f1) == dict + + +def test_deserialize_with_mismatched_field_types(): + json = '{"event": {"data": "Hello world!"} }' + s = C16.schema() + obj = s.loads(json) + assert obj.event is not None + assert obj.event.data == "Hello world!"