Skip to content

Commit ae03f55

Browse files
Jonathan Comoharleyk
authored andcommitted
Skip null attributes post serialization for maps (pynamodb#455)
* Skip null attributes post serialization for maps
1 parent 1399f91 commit ae03f55

File tree

2 files changed

+21
-4
lines changed

2 files changed

+21
-4
lines changed

pynamodb/attributes.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -735,9 +735,7 @@ def serialize(self, values):
735735
rval = {}
736736
for k in values:
737737
v = values[k]
738-
# Continue to serialize NULL values in "raw" map attributes for backwards compatibility.
739-
# This special case behavior for "raw" attribtues should be removed in the future.
740-
if not self.is_raw() and v is None:
738+
if self._should_skip(v):
741739
continue
742740
attr_class = self._get_serialize_class(k, v)
743741
if attr_class is None:
@@ -751,7 +749,12 @@ def serialize(self, values):
751749
attr = self._get_attributes().get(k)
752750
attr_name = attr.attr_name if attr else k
753751

754-
rval[attr_name] = {attr_key: attr_class.serialize(v)}
752+
serialized = attr_class.serialize(v)
753+
if self._should_skip(serialized):
754+
# Check after we serialize in case the serialized value is null
755+
continue
756+
757+
rval[attr_name] = {attr_key: serialized}
755758

756759
return rval
757760

@@ -788,6 +791,11 @@ def as_dict(self):
788791
result[key] = value.as_dict() if isinstance(value, MapAttribute) else value
789792
return result
790793

794+
def _should_skip(self, value):
795+
# Continue to serialize NULL values in "raw" map attributes for backwards compatibility.
796+
# This special case behavior for "raw" attribtues should be removed in the future.
797+
return not self.is_raw() and value is None
798+
791799
@classmethod
792800
def _get_serialize_class(cls, key, value):
793801
if not cls.is_raw():

pynamodb/tests/test_attributes.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class CustomAttrMap(MapAttribute):
5151

5252
class DefaultsMap(MapAttribute):
5353
map_field = MapAttribute(default={})
54+
string_field = UnicodeAttribute(null=True)
5455

5556

5657
class TestAttributeDescriptor:
@@ -574,6 +575,14 @@ def test_null_attribute_subclassed_map(self):
574575
serialized = attr.serialize(null_attribute)
575576
assert serialized == {}
576577

578+
def test_null_attribute_map_after_serialization(self):
579+
null_attribute = {
580+
'string_field': '',
581+
}
582+
attr = DefaultsMap()
583+
serialized = attr.serialize(null_attribute)
584+
assert serialized == {}
585+
577586
def test_map_of_map(self):
578587
attribute = {
579588
'name': 'Justin',

0 commit comments

Comments
 (0)