1

So I am trying to work with an api currently which returns json data such as:

 {
    "emp1" : {
      "EmpName" : "Chris Jackman",
      "EmpAge" : "34",
      "EmpGender" : "Male",
      "EmpDept" : "IT",
      "EmpDesg" : "Project Manager"
      "EmpSal": {
                  "2019": 20000
                  "2020": 23000
 },

    "emp2" : {
      "EmpName" : "Mary Jane",
      "EmpAge" : "27",
      "EmpGender" : "Female",
      "EmpDept" : "IT"
  }
}

Occasionally when we query the API one of these fields will be missing. When we try to access it

my_var = my_json["emp2"]["EmpDesg"]

Which will return a key error:

data_dict["EmpDesg"] = my_json["emp2"]["EmpDesg"]
KeyError: 'EmpDesg'

Is there a way to neatly deal with json paths missing rather than wrapping each field in a try catch:

    try:
        data_dict["EmpName"] = my_json["emp1"]["EmpName"]
    except KeyError as e:
        data_dict["EmpName"] = ""

    try:
        data_dict["EmpAge"] = my_json["emp1"]["EmpAge"]
    except KeyError as e:
        data_dict["EmpAge"] = ""

    try:
        data_dict["EmpGender"] = my_json["emp1"]["EmpGender"]
    except KeyError as e:
        data_dict["EmpGender"] = ""

    try:
        data_dict["salary"] = my_json["emp1"]["EmpSal"]["2020"]
    except KeyError as e:
        data_dict["salary"] = ""

2 Answers 2

1

If you want to check if a key exists, use "key" in data, not a try, except KeyError

Otherwise, if all you want is a default when a key doesn't exist, use .get() with the default parameter

emp1 = my_json["emp1"]
data_dict = {
  "EmpName": emp1.get("EmpName", '')
  "EmpAge": emp1.get("EmpAge", '')
}

Or

keys = ['EmpName', 'EmpAge']
data_dict = {k: emp1.get(k, '') for k in keys}
Sign up to request clarification or add additional context in comments.

Comments

0

To check if a path of arbitrary length exists in a given dict:

def path_exists(d, path) -> bool:
    """Return True if path exists in given dict."""
    next = d
    while path:
        k = path.pop(0)
        if k in next:
            next = next[k]
        else:
            return False

    return True

For example:


In [4]: path_exists(d, ['emp1', 'EmpName'])
Out[4]: True

In [5]: path_exists(d, ['emp1', 'EmpSal', '2019'])
Out[5]: True

In [6]: path_exists(d, ['emp1', 'EmpSal', '2018'])
Out[6]: False

So you can check whether the path exists (just once) before confidently traversing the dict.

Comments

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.