kaviya .P
kaviya .P

Reputation: 479

Generic way to get the value of key in nested json using python

I was new to python, my requirement is to check whether the given key exists on the json or not. Json will not be same all the time. So, am looking for the generic function to check whether the key exists. It works for simple json , but returns nothing when the json itself has another json with an jsonarray inside as shown below:

{
  "id": "1888741f-173a-4366-9fa0-a156d8734972",
  "type": "events",
  "version": "1.0.0",
  "count": 3,
  "payload": {
    "cmevents": [
      {
        "exit_code": "0dbc2745-a964-4ce3-b7a0-bd5295afc620",
        "sourceEventType": "test01",
        "sourceType": "test",
        product:{
        "productCode":"101"
        }
      },
      {
        "exit_code": "1dbc2745-a964-4ce3-b7a0-bd5295afc620",
        "sourceEventType": "test02",
        "sourceType": "test",
        product:{
        "productCode":"102"
        }
      },
      {
        "exit_code": "2dbc2745-a964-4ce3-b7a0-bd5295afc620",
        "sourceEventType": "test03",
        "sourceType": "test",
        product:{
        "productCode":"103"
        }
      }
    ]
  }
}

from the above json , i wants to check the key sourceEventType exists in all items of cmevents list. Following is the function I have used

def checkElementsExist(element, JSON, path, whole_path):
    if element in JSON:
        path = path + element + ' = ' + JSON[element].encode('utf-8')
        whole_path.append(path)
        //
    for key in JSON:
        if isinstance(JSON[key], dict):
            finds(element, JSON[key], path + key + '.', whole_path)

To call the function:

whole_path = []
finds('sourceEventType', json, '', whole_path)

Can anyone please help me with the right solution

Upvotes: 0

Views: 385

Answers (1)

nlta
nlta

Reputation: 1914

A recursive function is probably an easier approach here.

  1. Parse the json using json.loads(text)
  2. Search the tree
import json
text = json.loads(".....")
def search_for_key(key, content) -> bool:
    # Search each item of the list
    # if found return true
    if isinstance(content, list):
        for elem in content:
            if search_for_key(key, elem):
                return True
    # Search each key of the dictionary for match
    # If the key isn't a match try searching the value
    # of the key in the dictionary
    elif isinstance(content, dict):
        for key_in_json in content:
            if key_in_json == key:
                return True
            if search_for_key(key, content[key_in_json]):
                return True
    # If here it's a number or string. There is no where else to go
    # return false
    else:
        return False
print(search_for_key("some_key?", text))

It's definitely possible to make your path approach work BUT you're doing need to keep track of what paths you haven't explored yet using a stack/queue (and you get this for free with a recursive function).

Upvotes: 1

Related Questions