2

I get from an API a Json object. The structure of the Json object might be different every time I run the script.

Let's say that "json_answer" is the json answer and I am looking for the value of the key 'data' that I want to store in "var", this key may not exist every time I run the script.

I would like to know if there is a shortcut for this code (one line):

try:
    var = json_answer['data']
except:
    var = None

EDIT :

Thank you for the answer, I already know about get. But I am looking very deep in the dictionary and I don't want to try all the "levels".

Let me clarify with this example :

dict = {'data':{'values':{'value':True}}}

print(dict['data']['values'].get('time', False)) # print false
print(dict['data']['values'].get('value', False)) # print True

I don't know in which level of the dict I might have a problem (the key exist or not). I just have this "PATH" ['data']['values']['value'] and if want to know if it exists or not. How can I do it with "get" ?


SOLUTION :

Based on @Ryan♦ solution and extended to JSON file that contains dict and list inside :

def _get(obj, keys, default=None):

    for key in keys:
        if isinstance(obj, dict):
            if key not in obj:
                return default
        elif isinstance(obj, list):
            if not len(obj) > key:
                return default
        else:
            return default
    obj = obj[key]
    return obj
4
  • Do you mean the 'data' key won’t exist every time? And is NULL supposed to be None? Commented Jan 27, 2017 at 5:01
  • Thanks, i edited my post in order to clarify the question. Commented Jan 27, 2017 at 5:14
  • Can you do it recursively? Commented Jan 27, 2017 at 5:15
  • You can use in for that. if 'data' in json_answer, etc. Commented Jan 27, 2017 at 5:56

3 Answers 3

2

There’s nothing built-in, but if you write a function for it, it’s rather nice:

def get_path(obj, keys, default=None):
    for key in keys:
        try:
            obj = obj[key]
        except (KeyError, IndexError):
            return default

    return obj

d = {'data': {'values': {'value': True}}}

print(get_path(d, ['data', 'values', 'time'], default=False))
print(get_path(d, ['data', 'values', 'value'], default=False))
Sign up to request clarification or add additional context in comments.

2 Comments

Hi Ryan, it works if the JSON file contains only dictionaries. Please check my update (section: Solution). Based on your function i added the "list" case.
@YassineBelmamoun: I’m not sure which update you’re referring to, but see edit?
2

Use .get(). It will return None when the key is not present

 var = json_answer.get('data')

If you want to specify a default value to the var variable when the key is not present you can specify it as a second argument to the .get() function.

 var = json_answer.get('data', 'default_value')

Demo:

import json

jsonobj = json.loads('{"a": "hello"}')
print jsonobj.get('a')
print jsonobj.get('b')
print jsonobj.get('b', "BYE")

Output:

hello
None
BYE

You can try something like this for your nested case.

c={}
d = {'data':{'values':{'value':True}}}
var1 = d.get('aa', c).get('bb', c).get('cc', c) or None
var2 = d.get('data', c).get('values', c).get('value', c)
print var1
print var2

Output:

None
True

4 Comments

Thanks for the answer, i updated my question. Your solution works but not for my specific case.
@YassineBelmamoun Check now. You will get None when the key is not found.
It works, but it's not a pythonic solution. I think the best solution would be to use a function as described by Ryan. But thank you very much for your help.
@YassineBelmamoun Agree that it's more Pythonic.
0

You could do this:

>>> d =  {'data': {'values': {'value': True}}}
>>> d.get('data', {}).get('values', {}).get('time', False)
False
>>> d.get('data', {}).get('values', {}).get('value', False)
True

3 Comments

It works, but it's not a pythonic solution. I think the best solution would be to use a function as described by Ryan since there is nothing built-in. But thank you very much for your help.
Why do you think it's not a Pythonic solution?
I would like to avoid using three time the function "get" and repeat the definition of the default value. Thank you very much for your help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.