diff --git a/sdk/basyx/aas/adapter/json/json_serialization.py b/sdk/basyx/aas/adapter/json/json_serialization.py index 155aced55..2d9045c61 100644 --- a/sdk/basyx/aas/adapter/json/json_serialization.py +++ b/sdk/basyx/aas/adapter/json/json_serialization.py @@ -256,10 +256,8 @@ def _qualifier_to_json(cls, obj: model.Qualifier) -> Dict[str, object]: :return: dict with the serialized attributes of this object """ data = cls._abstract_classes_to_json(obj) - if obj.value: - data["value"] = ( - model.datatypes.xsd_repr(obj.value) if obj.value is not None else None - ) + if obj.value is not None: + data["value"] = model.datatypes.xsd_repr(obj.value) if obj.value_id: data["valueId"] = obj.value_id # Even though kind is optional in the schema, it's better to always serialize it instead of specifying @@ -278,10 +276,8 @@ def _extension_to_json(cls, obj: model.Extension) -> Dict[str, object]: :return: dict with the serialized attributes of this object """ data = cls._abstract_classes_to_json(obj) - if obj.value: - data["value"] = ( - model.datatypes.xsd_repr(obj.value) if obj.value is not None else None - ) + if obj.value is not None: + data["value"] = model.datatypes.xsd_repr(obj.value) if obj.refers_to: data["refersTo"] = list(obj.refers_to) if obj.value_type: diff --git a/sdk/basyx/aas/adapter/xml/xml_serialization.py b/sdk/basyx/aas/adapter/xml/xml_serialization.py index 8570add66..f11ef503b 100644 --- a/sdk/basyx/aas/adapter/xml/xml_serialization.py +++ b/sdk/basyx/aas/adapter/xml/xml_serialization.py @@ -328,7 +328,7 @@ def qualifier_to_xml( NS_AAS + "valueType", text=model.datatypes.XSD_TYPE_NAMES[obj.value_type] ) ) - if obj.value: + if obj.value is not None: et_qualifier.append(_value_to_xml(obj.value, obj.value_type)) if obj.value_id: et_qualifier.append(reference_to_xml(obj.value_id, NS_AAS + "valueId")) @@ -354,7 +354,7 @@ def extension_to_xml( text=model.datatypes.XSD_TYPE_NAMES[obj.value_type], ) ) - if obj.value: + if obj.value is not None: et_extension.append(_value_to_xml(obj.value, obj.value_type)) # type: ignore # (value_type could be None) if len(obj.refers_to) > 0: refers_to = _generate_element(NS_AAS + "refersTo") diff --git a/sdk/test/adapter/json/test_json_serialization_deserialization.py b/sdk/test/adapter/json/test_json_serialization_deserialization.py index 5e815ad92..725719a4a 100644 --- a/sdk/test/adapter/json/test_json_serialization_deserialization.py +++ b/sdk/test/adapter/json/test_json_serialization_deserialization.py @@ -125,3 +125,23 @@ def test_example_all_examples_serialization_deserialization(self) -> None: json_identifiable_store = read_aas_json_file(file, failsafe=False) checker = AASDataChecker(raise_immediately=True) checker.check_identifiable_store(json_identifiable_store, data) + + +class JsonSerializationDeserializationFalsyValueTest(unittest.TestCase): + def test_falsy_extension_and_qualifier_values(self) -> None: + for value_type, value in ((model.datatypes.Int, 0), + (model.datatypes.Decimal, model.datatypes.Decimal("0")), + (model.datatypes.Boolean, False)): + with self.subTest(value_type=value_type): + submodel = model.Submodel( + "https://example.org/falsy", + extension=[model.Extension("e", value_type=value_type, value=value)], + qualifier=[model.Qualifier("q", value_type=value_type, value=value)], + ) + file = io.StringIO() + write_aas_json_file(file=file, data=model.DictIdentifiableStore([submodel])) + file.seek(0) + read = read_aas_json_file(file, failsafe=False).get_item("https://example.org/falsy") + assert isinstance(read, model.Submodel) + self.assertEqual(value, read.get_extension_by_name("e").value) + self.assertEqual(value, read.get_qualifier_by_type("q").value) diff --git a/sdk/test/adapter/xml/test_xml_serialization_deserialization.py b/sdk/test/adapter/xml/test_xml_serialization_deserialization.py index aae0ce214..ec17095f0 100644 --- a/sdk/test/adapter/xml/test_xml_serialization_deserialization.py +++ b/sdk/test/adapter/xml/test_xml_serialization_deserialization.py @@ -90,3 +90,21 @@ def test_submodel_serialization_deserialization(self) -> None: ) checker = AASDataChecker(raise_immediately=True) checker.check_submodel_equal(submodel2, submodel) + + +class XMLSerializationDeserializationFalsyValueTest(unittest.TestCase): + def test_falsy_extension_and_qualifier_values(self) -> None: + for value_type, value in ((model.datatypes.Int, 0), + (model.datatypes.Decimal, model.datatypes.Decimal("0")), + (model.datatypes.Boolean, False)): + with self.subTest(value_type=value_type): + submodel = model.Submodel( + "https://example.org/falsy", + extension=[model.Extension("e", value_type=value_type, value=value)], + qualifier=[model.Qualifier("q", value_type=value_type, value=value)], + ) + read = _serialize_and_deserialize(model.DictIdentifiableStore([submodel])).get_item( + "https://example.org/falsy") + assert isinstance(read, model.Submodel) + self.assertEqual(value, read.get_extension_by_name("e").value) + self.assertEqual(value, read.get_qualifier_by_type("q").value)