diff --git a/jmespath/visitor.py b/jmespath/visitor.py index 15fb177..f3a4100 100644 --- a/jmespath/visitor.py +++ b/jmespath/visitor.py @@ -58,7 +58,7 @@ def _is_actual_number(x): class Options(object): """Options to control how a JMESPath function is evaluated.""" - def __init__(self, dict_cls=None, custom_functions=None): + def __init__(self, dict_cls=None, custom_functions=None, not_found_value=None): #: The class to use when creating a dict. The interpreter # may create dictionaries during the evaluation of a JMESPath # expression. For example, a multi-select hash will @@ -69,6 +69,7 @@ def __init__(self, dict_cls=None, custom_functions=None): # have predictable key ordering. self.dict_cls = dict_cls self.custom_functions = custom_functions + self.not_found_value = not_found_value class _Expression(object): @@ -133,9 +134,9 @@ def visit_subexpression(self, node, value): def visit_field(self, node, value): try: - return value.get(node['value']) + return value.get(node['value'], self._options.not_found_value) except AttributeError: - return None + return self._options.not_found_value def visit_comparator(self, node, value): # Common case: comparator is == or != diff --git a/tests/test_search.py b/tests/test_search.py index 4832079..c850707 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -62,3 +62,10 @@ def test_can_handle_decimals_as_numeric_type(self): result = decimal.Decimal('3') self.assertEqual(jmespath.search('[?a >= `1`].a', [{'a': result}]), [result]) + + +class TestNotFoundValueOption(unittest.TestCase): + def test_can_supply_custom_not_found_value(self): + opt = jmespath.Options(not_found_value='foo') + value = jmespath.search('b', {'a': 1}, opt) + self.assertEqual(value, 'foo')