From 47fe6b4822aff446299ce8f757650aa5982ba4a2 Mon Sep 17 00:00:00 2001 From: Chris Tsou Date: Thu, 9 May 2024 19:00:12 +0300 Subject: [PATCH] fix: Derived element json serialization (#1035) --- .../dataclass/serializers/test_dict.py | 21 +++++++++++++++++++ xsdata/formats/dataclass/models/generics.py | 2 +- xsdata/formats/dataclass/typing.py | 6 ++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/tests/formats/dataclass/serializers/test_dict.py b/tests/formats/dataclass/serializers/test_dict.py index d8767406..8b177bbf 100644 --- a/tests/formats/dataclass/serializers/test_dict.py +++ b/tests/formats/dataclass/serializers/test_dict.py @@ -3,6 +3,7 @@ from tests.fixtures.books import BookForm, Books from tests.fixtures.datatypes import Telephone from tests.fixtures.wrapper import Wrapper +from xsdata.formats.dataclass.models.generics import AnyElement, DerivedElement from xsdata.formats.dataclass.serializers import DictEncoder, DictFactory from xsdata.models.datatype import XmlDate from xsdata.models.xsd import Attribute @@ -107,3 +108,23 @@ def test_next_value(self): expected = expected[:-1] actual = [name for name, value in self.encoder.next_value(book)] self.assertEqual(expected, actual) + + def test_generics(self): + self.obj = AnyElement( + children=[ + AnyElement(qname="foo", text="bar"), + DerivedElement(qname="bar", value="1"), + DerivedElement(qname="bar", value=2), + ] + ) + result = self.encoder.encode(self.obj) + expected = { + "attributes": {}, + "children": [ + {"attributes": {}, "children": [], "qname": "foo", "text": "bar"}, + {"qname": "bar", "value": "1"}, + {"qname": "bar", "value": 2}, + ], + } + + self.assertEqual(expected, result) diff --git a/xsdata/formats/dataclass/models/generics.py b/xsdata/formats/dataclass/models/generics.py index a4092660..af1f7b4f 100644 --- a/xsdata/formats/dataclass/models/generics.py +++ b/xsdata/formats/dataclass/models/generics.py @@ -33,7 +33,7 @@ class AnyElement: class DerivedElement(Generic[T]): """Generic model wrapper for type substituted elements. - Example: eg. ... + Example: e.g. ... Args: qname: The element's qualified name diff --git a/xsdata/formats/dataclass/typing.py b/xsdata/formats/dataclass/typing.py index 7fd538cb..216301cb 100644 --- a/xsdata/formats/dataclass/typing.py +++ b/xsdata/formats/dataclass/typing.py @@ -7,6 +7,7 @@ Optional, Tuple, Type, + TypeVar, Union, ) @@ -152,6 +153,11 @@ def evaluate_attributes(annotation: Any, **_: Any) -> Result: def evaluate_element(annotation: Any, tokens: bool = False) -> Result: """Validate annotations for a xml element.""" + + # Only the derived element value field is allowed a typevar + if isinstance(annotation, TypeVar) and annotation.__bound__ is object: + annotation = object + types = (annotation,) origin = get_origin(annotation) args = get_args(annotation)