diff --git a/tests/codegen/mappers/test_dict.py b/tests/codegen/mappers/test_dict.py index f0d5fda4a..f82726c56 100644 --- a/tests/codegen/mappers/test_dict.py +++ b/tests/codegen/mappers/test_dict.py @@ -89,13 +89,13 @@ def test_build_class_attribute_from_empty_list(self): AttrTypeFactory.native(DataType.ANY_SIMPLE_TYPE, tag=Tag.ELEMENT), ], ) - restrictions = Restrictions(min_occurs=1, max_occurs=sys.maxsize) + restrictions = Restrictions(min_occurs=0, max_occurs=sys.maxsize) self.assertEqual(expected, target.attrs[0]) self.assertEqual(restrictions, target.attrs[0].restrictions) def test_build_class_attribute_from_dict(self): target = ClassFactory.create() - data = {"sub1": 1, "sub2": "value"} + data = {"sub1": 1, "sub2": "value", "sub3": None} DictMapper.build_class_attribute(target, "a", data) expected = AttrFactory.create( @@ -113,9 +113,14 @@ def test_build_class_attribute_from_dict(self): attrs=[ AttrFactory.native(DataType.SHORT, name="sub1"), AttrFactory.native(DataType.STRING, name="sub2"), + AttrFactory.native(DataType.STRING, name="sub3"), ], ) self.assertEqual(expected, target.attrs[0]) self.assertEqual(expected_inner, target.inner[0]) self.assertEqual(1, len(target.inner)) + + self.assertFalse(target.inner[0].attrs[0].restrictions.is_optional) + self.assertFalse(target.inner[0].attrs[1].restrictions.is_optional) + self.assertTrue(target.inner[0].attrs[2].restrictions.is_optional) diff --git a/xsdata/codegen/mappers/dict.py b/xsdata/codegen/mappers/dict.py index 3f5b5cf51..a62be0ba4 100644 --- a/xsdata/codegen/mappers/dict.py +++ b/xsdata/codegen/mappers/dict.py @@ -71,4 +71,4 @@ def build_class_attribute(cls, target: Class, name: str, value: Any): else: attr_type = cls.build_attr_type(name, value) - cls.build_attr(target, name, attr_type) + cls.build_attr(target, name, attr_type, value=value) diff --git a/xsdata/codegen/mappers/mixins.py b/xsdata/codegen/mappers/mixins.py index 59c1d7736..d05002e64 100644 --- a/xsdata/codegen/mappers/mixins.py +++ b/xsdata/codegen/mappers/mixins.py @@ -7,6 +7,8 @@ from xsdata.utils import collections from xsdata.utils.namespaces import split_qname +_UNSET = object() + class RawDocumentMapper: """Mixin class for raw json/xml documents.""" @@ -20,6 +22,7 @@ def build_attr( parent_namespace: Optional[str] = None, tag: str = Tag.ELEMENT, sequence: int = 0, + value: Any = _UNSET, ): """Build an attr for the given class instance. @@ -30,6 +33,7 @@ def build_attr( parent_namespace: The parent namespace tag: The attr tag sequence: The attr sequence number + value: The attr sample value """ namespace, name = split_qname(qname) namespace = cls.select_namespace(namespace, parent_namespace, tag) @@ -43,6 +47,10 @@ def build_attr( attr.restrictions.min_occurs = 1 attr.restrictions.max_occurs = 1 + + if value is None: + attr.restrictions.min_occurs = 0 + cls.add_attribute(target, attr) @classmethod