Skip to content

Commit

Permalink
JSON Parser: try all someclasses for element nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
tefra committed Jun 14, 2021
1 parent 54ebc76 commit d7fab05
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 0 deletions.
20 changes: 20 additions & 0 deletions tests/fixtures/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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"})
Expand Down
8 changes: 8 additions & 0 deletions tests/formats/dataclass/parsers/test_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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}

Expand Down
7 changes: 7 additions & 0 deletions xsdata/formats/dataclass/parsers/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down

0 comments on commit d7fab05

Please sign in to comment.