Skip to content

Commit c9b001c

Browse files
committed
Handle None values in list parsing to fix TypeError
When services like RDS Data API return lists with null values (e.g. longValues: [123, null, 456]), _handle_list() passes None to type parsers like int(), causing: TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType' Add null checking in _handle_list() to preserve None values instead of attempting to parse them. Treats all lists as sparse.
1 parent 30e7164 commit c9b001c

2 files changed

Lines changed: 59 additions & 1 deletion

File tree

awscli/botocore/parsers.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,12 @@ def _handle_list(self, shape, node):
347347
parsed = []
348348
member_shape = shape.member
349349
for item in node:
350-
parsed.append(self._parse_shape(member_shape, item))
350+
# Treat all lists as sparse during parsing to safely handle null
351+
# elements that may be present in service responses.
352+
if item is None:
353+
parsed.append(None)
354+
else:
355+
parsed.append(self._parse_shape(member_shape, item))
351356
return parsed
352357

353358
def _default_handle(self, shape, value):

tests/unit/botocore/test_parsers.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,3 +1640,56 @@ def test_can_handle_generic_error_message(parser, body):
16401640
)
16411641
assert parsed['Error'] == {'Code': '503', 'Message': 'Service Unavailable'}
16421642
assert parsed['ResponseMetadata']['HTTPStatusCode'] == 503
1643+
1644+
1645+
class TestNullInListParsing(unittest.TestCase):
1646+
def test_handles_null_in_list(self):
1647+
parser = parsers.JSONParser()
1648+
body = b'{"items":[1,null,3]}'
1649+
output_shape = model.StructureShape(
1650+
'OutputShape',
1651+
{'type': 'structure', 'members': {'items': {'shape': 'ItemList'}}},
1652+
model.ShapeResolver(
1653+
{
1654+
'ItemList': {
1655+
'type': 'list',
1656+
'member': {'shape': 'ItemType'},
1657+
},
1658+
'ItemType': {'type': 'integer'},
1659+
}
1660+
),
1661+
)
1662+
parsed = parser.parse(
1663+
{'body': body, 'headers': {}, 'status_code': 200}, output_shape
1664+
)
1665+
self.assertEqual(parsed['items'], [1, None, 3])
1666+
1667+
def test_handles_null_in_nested_list(self):
1668+
parser = parsers.RestJSONParser()
1669+
body = b'{"data":[[{"values":[1,null,3]}]]}'
1670+
output_shape = model.StructureShape(
1671+
'OutputShape',
1672+
{'type': 'structure', 'members': {'data': {'shape': 'DataList'}}},
1673+
model.ShapeResolver(
1674+
{
1675+
'DataList': {
1676+
'type': 'list',
1677+
'member': {'shape': 'ItemList'},
1678+
},
1679+
'ItemList': {'type': 'list', 'member': {'shape': 'Item'}},
1680+
'Item': {
1681+
'type': 'structure',
1682+
'members': {'values': {'shape': 'ValueList'}},
1683+
},
1684+
'ValueList': {
1685+
'type': 'list',
1686+
'member': {'shape': 'ValueType'},
1687+
},
1688+
'ValueType': {'type': 'integer'},
1689+
}
1690+
),
1691+
)
1692+
parsed = parser.parse(
1693+
{'body': body, 'headers': {}, 'status_code': 200}, output_shape
1694+
)
1695+
self.assertEqual(parsed['data'][0][0]['values'], [1, None, 3])

0 commit comments

Comments
 (0)