diff --git a/boto3/dynamodb/types.py b/boto3/dynamodb/types.py index f358b12f55..17a0cd46bd 100644 --- a/boto3/dynamodb/types.py +++ b/boto3/dynamodb/types.py @@ -189,7 +189,7 @@ def _is_set(self, value): return False def _is_type_set(self, value, type_validator): - if self._is_set(value): + if self._is_set(value) and len(value) > 0: if False not in map(type_validator, value): return True return False @@ -237,6 +237,11 @@ def _serialize_l(self, value): return [self.serialize(v) for v in value] def _serialize_m(self, value): + for k in value: + if not isinstance(k, str): + raise TypeError( + f'Map keys must be strings, got {type(k).__name__}: {k!r}' + ) return {k: self.serialize(v) for k, v in value.items()} diff --git a/tests/unit/dynamodb/test_types.py b/tests/unit/dynamodb/test_types.py index 0a6c2a07f3..680a78f01b 100644 --- a/tests/unit/dynamodb/test_types.py +++ b/tests/unit/dynamodb/test_types.py @@ -143,6 +143,14 @@ def test_serialize_map(self): 'M': {'foo': {'S': 'bar'}, 'baz': {'M': {'biz': {'N': '1'}}}} } + def test_serialize_empty_set_raises_error(self): + with pytest.raises(TypeError, match=r'Unsupported type'): + self.serializer.serialize(set()) + + def test_serialize_map_with_non_string_key_raises_error(self): + with pytest.raises(TypeError, match=r'Map keys must be strings'): + self.serializer.serialize({1: 'a'}) + class TestDeserializer(unittest.TestCase): def setUp(self):