diff --git a/flask_restx/fields.py b/flask_restx/fields.py index 3212856c..031fdd61 100644 --- a/flask_restx/fields.py +++ b/flask_restx/fields.py @@ -66,6 +66,10 @@ def is_indexable_but_not_string(obj): return not hasattr(obj, "strip") and hasattr(obj, "__iter__") +def is_integer_indexable(obj): + return isinstance(obj, list) or isinstance(obj, tuple) + + def get_value(key, obj, default=None): """Helper for pulling a keyed value off various types of objects""" if isinstance(key, int): @@ -91,6 +95,11 @@ def _get_value_for_key(key, obj, default): return obj[key] except (IndexError, TypeError, KeyError): pass + if is_integer_indexable(obj): + try: + return obj[int(key)] + except (IndexError, TypeError, ValueError): + pass return getattr(obj, key, default) diff --git a/tests/test_fields.py b/tests/test_fields.py index 0a5312cf..e54fb6a9 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1385,3 +1385,21 @@ def __getitem__(self, n): obj = Test("hi") assert fields.get_value("value", obj) == "hi" + + def test_get_value_int_indexable_list(self): + assert fields.get_value('bar.0', {'bar': [42]}) == 42 + + def test_get_value_int_indexable_list_with_str(self): + assert fields.get_value('bar.abc', {'bar': [42]}) is None + + def test_get_value_int_indexable_nested_list(self): + assert fields.get_value('bar.0.val', {'bar': [{'val': 42}]}) == 42 + + def test_get_value_int_indexable_tuple_with_str(self): + assert fields.get_value('bar.abc', {'bar': (42, 43)}) is None + + def test_get_value_int_indexable_tuple(self): + assert fields.get_value('bar.0', {'bar': (42, 43)}) == 42 + + def test_get_value_int_indexable_nested_tuple(self): + assert fields.get_value('bar.0.val', {'bar': [{'val': 42}]}) == 42