Search code examples
pythonjsonprocesstreeview

Create process tree form json file. in python


I need some assistance on a somewhat simple issue.

I'm trying to convert the content of a json file from this:

    {   "Timestamp": "Timestamp",
        "name": "SVCHOST.EXE",
        "icon": "binary_icon.png",
        "Process": SVCHOST.EXE,
        "Pid": "876",
        "PPID": "500"],
        "children": [Process details])
    },
    {   "Timestamp":"Timestamp",
        "name": "LSAS.EXE",
        "icon": "binary_icon.png",
        "Process": "LSAS.EXE",
        "Pid": "500",
        "PPID": "4"],
        "children": [Process details])
    },
    {   "Timestamp":"Timestamp",
        "name": "SYSTEM",
        "icon": "binary_icon.png",
        "Process": "SYSTEM",
        "Pid": "4",
        "PPID": "0"],
        "children": [Process details])
    }

To this:

{
"name": "Root", 
"children": [
    {
        "name": "4", 
        "children": [
            {
                "name": "500", 
                "children": [
                    {
                        "name": "876", 
                        "children": []
                    }
                ]
            }
        ]
    }
}

To create a node tree graph in the end.

But after a lot of trial and error, and still not close to the output I need. I'm asking for some pointer, tips or tricks. Any help is much appreciated.

Thanks,

Here is my most recent attempt.

import json

links = ({
"Timestamp": "Timestamp",
    "name": "SVCHOST.EXE",
    "icon": "binary_icon.png",
    "Process": "SVCHOST.EXE",
    "Pid": "876",
    "PPID": "500",
    "children": "Process_details"
},
  {
    "Timestamp":"Timestamp",
    "name": "LSAS.EXE",
    "icon": "binary_icon.png",
    "Process": "LSAS.EXE",
    "Pid": "500",
    "PPID": "4",
    "children": "Process_details"
},
  {
    "Timestamp":"Timestamp",
    "name": "SYSTEM",
    "icon": "binary_icon.png",
    "Process": "SYSTEM",
    "Pid": "4",
    "PPID": "0",
    "children": "Process_details"
})



parent_proc_node = {}
root = {'name': 'Root', 'children': []}
for item in procs:
    parent_node = parent_proc_node.get(item['Pid'])
    if not parent_node:
        parent_proc_node[item['Pid']] = parent_node = {'name': item['PPID']}
        root['children'].append(parent_node)
    parent_proc_node[item['PPID']] = child_node = {'name': item['Pid']}
    parent_node.setdefault('children', []).append(child_node)

print json.dumps(root, indent=4)

Current output:

{
"name": "Root", 
"children": [
    {
        "name": "500", 
        "children": [
            {
                "name": "876", 
                "children": [
                    {
                        "name": "500", 
                        "children": [
                            {
                                "name": "4"
                            }
                        ]
                    }
                ]
            }
        ]
    }
}

The output is now what I want, but im still not able to correctly match parent process with children. What am I doing wrong?

The correct output would be like this:

{
"name": "Root", 
"children": [
    {
        "name": "4", 
        "children": [
            {
                "name": "500", 
                "children": [
                    {
                        "name": "876", 
                        "children": [
                            {
                                "name": ""
                            }
                        ]
                    }
                ]
            }
        ]
    }
}

Solution

  • Here's some code that does what I think you want. It processes the links (which I turned into a list, since JSON doesn't have tuples), converting it into the nested structure that you show as the final correct output. I've also added a couple of new records so that some parents have multiple children.

    The trick is to first create a dictionary (ids) that captures the parent-child relationship of the process IDs.

    import json
    
    links = [
        {
            "Timestamp": "Timestamp",
            "name": "SVCHOST.EXE",
            "icon": "binary_icon.png",
            "Process": "SVCHOST.EXE",
            "Pid": "876",
            "PPID": "500",
            "children": "Process_details"
        },
        {
            "Timestamp": "Timestamp",
            "name": "LSAS.EXE",
            "icon": "binary_icon.png",
            "Process": "LSAS.EXE",
            "Pid": "500",
            "PPID": "4",
            "children": "Process_details"
        },
        {
            "Timestamp": "Timestamp",
            "name": "LSAS.EXE",
            "icon": "binary_icon.png",
            "Process": "LSAS.EXE",
            "Pid": "510",
            "PPID": "4",
            "children": "Process_details"
        },
        {
            "Timestamp": "Timestamp",
            "name": "LSAS.EXE",
            "icon": "binary_icon.png",
            "Process": "LSAS.EXE",
            "Pid": "600",
            "PPID": "510",
            "children": "Process_details"
        },
        {
            "Timestamp": "Timestamp",
            "name": "SYSTEM",
            "icon": "binary_icon.png",
            "Process": "SYSTEM",
            "Pid": "4",
            "PPID": "0",
            "children": "Process_details"
        }
    ]
    
    # Create a dict linking each pid to its parent
    ids = {}
    for d in links:
        # Use "0" as the ppid if "PPID" field is an empty string 
        ppid, pid = d["PPID"] or "0", d["Pid"]
        ids.setdefault(ppid, []).append(pid)
    print(ids)
    
    # Nest the data for each pid in its parent's dict
    def insert(lst, ppid, name):
        if ppid in ids:
            children = []
            lst.append({"name": name, "children": children})
            for pid in ids[ppid]:
                insert(children, pid, pid)
        else:
            children = [{"name": ""}]
            lst.append({"name": name, "children": children})
    
    nested = []
    insert(nested, "0", "Root")
    print(json.dumps(nested[0], indent=4))
    

    output

    {'500': ['876'], '4': ['500', '510'], '510': ['600'], '0': ['4']}
    {
        "name": "Root",
        "children": [
            {
                "name": "4",
                "children": [
                    {
                        "name": "500",
                        "children": [
                            {
                                "name": "876",
                                "children": [
                                    {
                                        "name": ""
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        "name": "510",
                        "children": [
                            {
                                "name": "600",
                                "children": [
                                    {
                                        "name": ""
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        ]
    }