jmespath.py
jmespath.py copied to clipboard
Custom "None" value when search fails
Hi, thanks for this awesome lib! One question: it seems to be impossible to set a custom return in case the search fails.
E.g.
not_found = object()
jmespath.search('foo.aaa', {'foo': {'bar': 'baz'}}) # I need `not_found`, not `None`
Is this by design or are you open to supporting that?
I see this was discussed at https://github.com/jmespath/jmespath.py/issues/113
But the proposed solution of contains isn't great, as it requires 2 searches.
You may try
jmespath.search('foo.aaa', {'foo': {'bar': 'baz'}}) or 'not_found'
@yashpokar
Not enough for this problem.
This will make 'not_found' be returned when 'foo.aaa' is None, like here: {'foo': {'aaa': None}}. That's why it's important to differentiate a valid None from a not found value.
@fjsj you're right :+1:
Hi, thanks for this awesome lib! One question: it seems to be impossible to set a custom return in case the search fails.
E.g.
not_found = object() jmespath.search('foo.aaa', {'foo': {'bar': 'baz'}}) # I need `not_found`, not `None`Is this by design or are you open to supporting that? I see this was discussed at #113 But the proposed solution of
containsisn't great, as it requires 2 searches.
Good proposal!!
It has to be differentiated between the legal value 'null' for an existing key and a non-existing key. JMESPath search should return another object than None if a key is not found.
E.g. allow to define an object NotFound as option. If not defined use None for not found. So you are backward compatible.
any updates on this?
Any updates? This seems like quite an important thing to solve imo.
+1
+1
If anyone is looking for a hack, this is what I am using until this issues is resolved. The key_exists function below will check for true existence of key:
def key_exists(key: str, obj: Any, separator='.') -> bool:
keys = key.split(separator)
for k in keys:
if isinstance(obj, dict):
if k in obj:
obj = obj[k]
else:
return False
else:
return False
return True
To use, check if the search result is None and if the key doesn't exist before implementing handling logic:
result = jmespath.search(search_string, source)
if result is None and not key_exists(search_string, source, separator="."):
if match_required:
# Handle search_string doesn't exist but match is required...
# Handle search_string doesn't exist and match isn't required, go ahead and assign a default value
# Implied else, search_string was found in source and it may be None
Please use caution, this will easily break when a more sophisticated jmespath expression is used.
Since jmespath doesn't care about fixing this, we've ended up using jsonpath-ng which supports everything that jmespath supports + handling None values. Best workaround.