1

I have Json file which Looks like Below. To get the list (given in example1,example2 and further) , I have to write nested for loop 5-6 times. Is there any easy way to write the code and get the end list ?

Example of Json file

{
"SecureConfig" :[
    {
        "Test" : [
            {
                "Test1" : [
                    {
                        "example1" : ["ls","cat abc.txt | grep wc -l"]
                    },
                    {
                        "example2" : ["ls","cat abc.txt | grep wc -l"]
                    }
                ],
                "Test2" : [
                    {
                        "example3" : ["ls","cat abc.txt | grep wc -l"] 
                    },
                    {
                        "example4" : ["ls","cat abc.txt | grep wc -l"]
                    }
                ]                  
            }
        ]
    }
]}

Loop that I have created is :-

config_file = open(FILE) 
data = json.load(config_file)

for index in range(len(data[module])):
    for ModuelName in data[module][index]:
        ModuleValue=data[module][index][ModuelName]
            for index2 in range(len(ModuleValue)):
                for SubModuleName in ModuleValue[index]:
                    SubModuleValue=ModuleValue[index2][SubModuleName]
                    for index3 in range(len(SubModuleValue)):
                        for keys3 in SubModuleValue[index3]:
                            print (SubModuleValue[index3][keys3])
  • 1
    Welcome back to Stack Overflow. As a refresher, please read [ask] and [mre]. This question is not clear. What does "end list of data" mean? What should the result be when you have this input, and why? What code did you try using, and why does it have loops at all, let alone deeply nested ones? Also, [please do not upload images of data when asking a question.](//meta.stackoverflow.com/q/285551). Instead, copy and paste the JSON example [with proper formatting](https://stackoverflow.com/help/formatting) as a multi-line code block. – Karl Knechtel Jul 30 '22 at 03:38
  • Updated the question as per your recommendation. Hope it's clear now. Let me know if still something is clear. – manav sharma Aug 02 '22 at 08:50
  • If this is not a debugging request, then please make sure that others can copy and paste the code, use it *on the example input*, and get the correct result. Also show what the result should be. I guess you are trying to get all the `["ls","cat abc.txt | grep wc -l"]` values, but not sure if I have that right, whether you want to take separate strings from those lists, etc. Also, do you really want to *print* everything, or would it be better to make a flat list of the results? – Karl Knechtel Aug 02 '22 at 20:43
  • Does https://stackoverflow.com/questions/2544055 answer your question? Or https://stackoverflow.com/questions/47367665 ? – Karl Knechtel Aug 02 '22 at 20:46

1 Answers1

1

If you just want to search a nested structure for lists where the first element is a string, then this code will work.

s = """{
"SecureConfig" :[
    {
        "Test" : [
            {
                "Test1" : [
                    {
                        "example1" : ["ls","cat abc.txt | grep wc -l"]
                    },
                    {
                        "example2" : ["ls","cat abc.txt | grep wc -l"]
                    }
                ],
                "Test2" : [
                    {
                        "example3" : ["ls","cat abc.txt | grep wc -l"] 
                    },
                    {
                        "example4" : ["ls","cat abc.txt | grep wc -l"]
                    }
                ]                  
            }
        ]
    }
]}"""

import json

def extract_values(d):
    result = []
    stack = [d]
    while stack:
        node = stack.pop()
        if type(node) is list:
            if len(node) != 0 and type(node[0]) is str:
                result.append(node)
            else:
                for e in node:
                    stack.append(e)
        elif type(node) is dict:
            for v in node.values():
                stack.append(v)
    return result
                

data = json.loads(s)
values = extract_values(data)
for v in values:
    print(v)

This will print

['ls', 'cat abc.txt | grep wc -l']
['ls', 'cat abc.txt | grep wc -l']
['ls', 'cat abc.txt | grep wc -l']
['ls', 'cat abc.txt | grep wc -l']

To also extract the keys, use this instead:

def extract_values(d):
    result = []
    stack = [d]
    while stack:
        node = stack.pop()
        if type(node) is list:
            for e in node:
                stack.append(e)
        elif type(node) is dict:
            for k, v in node.items():
                if type(v) == list and len(v) != 0 and type(v[0]) is str:
                    result.append((k, v))
                else:
                    stack.append(v)
    return result

This will print:

('example4', ['ls', 'cat abc.txt | grep wc -l'])
('example3', ['ls', 'cat abc.txt | grep wc -l'])
('example2', ['ls', 'cat abc.txt | grep wc -l'])
('example1', ['ls', 'cat abc.txt | grep wc -l'])
fafl
  • 7,222
  • 3
  • 27
  • 50
  • Thanks for the reply. Really appreciate your help. Is there a way i can get name of key as well , like --- key for value ['ls', 'cat abc.txt | grep wc -l'] is example1. By using pop function , we are losing the track of keys for the corresponding values. – manav sharma Aug 02 '22 at 18:46
  • Sure, added the code – fafl Aug 02 '22 at 19:26
  • Works perfect for my requirement. Thanks a lot for your help. My whole code looks good now. :) – manav sharma Aug 03 '22 at 07:01