From d7fab05c6de35532c2754c6c2d70dcb5e87a67cc Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 14 Jun 2021 22:06:32 +0300 Subject: [PATCH] JSON Parser: try all someclasses for element nodes --- tests/fixtures/models.py | 20 ++++++++++++++++++++ tests/formats/dataclass/parsers/test_json.py | 8 ++++++++ xsdata/formats/dataclass/parsers/json.py | 7 +++++++ 3 files changed, 35 insertions(+) diff --git a/tests/fixtures/models.py b/tests/fixtures/models.py index 6a61fb622..41d020183 100644 --- a/tests/fixtures/models.py +++ b/tests/fixtures/models.py @@ -40,6 +40,21 @@ class TypeDuplicate: x1: str = field(metadata={"name": "x"}) +@dataclass +class BaseA: + x: str + + +@dataclass +class BaseB(BaseA): + y: str + + +@dataclass +class BaseC(BaseB): + z: str + + @dataclass class ExtendedType: a: Optional[TypeA] = field(default=None) @@ -75,6 +90,11 @@ class UnionType: element: Union[TypeA, TypeB, TypeC, TypeD] +@dataclass +class BaseType: + element: BaseA + + @dataclass class AttrsType: index: int = field(metadata={"type": "Attribute"}) diff --git a/tests/formats/dataclass/parsers/test_json.py b/tests/formats/dataclass/parsers/test_json.py index d134d4ecb..bb8ef91fc 100644 --- a/tests/formats/dataclass/parsers/test_json.py +++ b/tests/formats/dataclass/parsers/test_json.py @@ -7,6 +7,8 @@ from tests.fixtures.books import BookForm from tests.fixtures.books import Books from tests.fixtures.models import AttrsType +from tests.fixtures.models import BaseC +from tests.fixtures.models import BaseType from tests.fixtures.models import ChoiceType from tests.fixtures.models import ExtendedType from tests.fixtures.models import TypeA @@ -223,6 +225,12 @@ def test_bind_dataclass_union(self): str(cm.exception), ) + def test_bind_dataclass_subclasses(self): + data = {"element": {"x": "1", "y": "foo", "z": "1.0"}} + actual = self.parser.bind_dataclass(data, BaseType) + + self.assertIsInstance(actual.element, BaseC) + def test_bind_attributes(self): data = {"attrs": {"a": 1, "b": 2}, "index": 1} diff --git a/xsdata/formats/dataclass/parsers/json.py b/xsdata/formats/dataclass/parsers/json.py index 60be71545..a598b1ff2 100644 --- a/xsdata/formats/dataclass/parsers/json.py +++ b/xsdata/formats/dataclass/parsers/json.py @@ -258,6 +258,13 @@ def bind_complex_type(self, meta: XmlMeta, var: XmlVar, data: Dict) -> Any: return self.bind_best_dataclass(data, meta.element_types) else: assert var.clazz is not None + + subclasses = set(self.context.get_subclasses(var.clazz)) + if subclasses: + # field annotation is an abstract/base type + subclasses.add(var.clazz) + return self.bind_best_dataclass(data, subclasses) + return self.bind_dataclass(data, var.clazz) def bind_derived_value(self, meta: XmlMeta, var: XmlVar, data: Dict) -> T: