Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert delimited string and value into hierarchical JSON with Python

I have data in the following format:

[['Director', 9010],
['Director - Product Manager', 9894],
['Director - Product Manager - Project Manager', 9080],
['Director - Product Manager - Project Manager - Staff', 5090],
['Director - Product Manager - Project Manager - Staff 2', 5087],
['Director - Product Manager - Project Manager 2', 9099],...]

and want an output that'll look something like this:

{
    'title': 'Director',
    'id': 9010,
    'children': [
        {
            'title': 'Product Manager',
            'id': 9894,
            'children': [
                {
                    'title': 'Project Manager',
                    'id': 9080,
                    'children': [
                        ...
                    ]
                },{
                    'title': 'Project Manager 2',
                    'id': 9099,
                    'children': [
                        ...
                    ]
                }],
                ...
            ]
        },
        ...
    ]
}

I've been toying around with dictionaries, but struggling to match the ids with the titles. Any suggestions are appreciated.

like image 458
dimvrco Avatar asked Nov 17 '25 22:11

dimvrco


1 Answers

An efficient way to do this is to make the outermost layer a list rather than a dict. As we iterate over each title in the string of titles we look for a dict with that title in the current list. If the title doesn't exist in the current list then we need to create a new dict. If it does exist, then we make the children list of that dict the new current list and proceed to look for the next title.

I've also written a recursive prune function which removes all empty children lists, once we've finished entering all the data, in case you want to do that.

import json

lst = [
    ['Director', 9010],
    ['Director - Product Manager', 9894],
    ['Director - Product Manager - Project Manager', 9080],
    ['Director - Product Manager - Project Manager - Staff', 5090],
    ['Director - Product Manager - Project Manager - Staff 2', 5087],
    ['Director - Product Manager - Project Manager 2', 9099],
]

# Search for a matching name in the current list.
# If it doesn't exist, create it.
def insert(lst, name, idnum):
    for d in lst:
        if d['title'] == name:
            break
    else:
        d = {'title': name, 'id': idnum, 'children': []}
        lst.append(d)
    return d['children']

# Remove empty child lists
def prune(lst):
    for d in lst:
        if d['children']:
            prune(d['children'])
        else:
            del d['children']

# Insert the data into the master list
master = []
for names, idnum in lst:
    lst = master
    for name in [s.strip() for s in names.split(' - ')]:
        lst = insert(lst, name, idnum)

prune(master)

# Get the top level dict from the master list
data = master[0]
print(json.dumps(data, indent=4))

output

{
    "title": "Director",
    "id": 9010,
    "children": [
        {
            "title": "Product Manager",
            "id": 9894,
            "children": [
                {
                    "title": "Project Manager",
                    "id": 9080,
                    "children": [
                        {
                            "title": "Staff",
                            "id": 5090
                        },
                        {
                            "title": "Staff 2",
                            "id": 5087
                        }
                    ]
                },
                {
                    "title": "Project Manager 2",
                    "id": 9099
                }
            ]
        }
    ]
}
like image 179
PM 2Ring Avatar answered Nov 19 '25 10:11

PM 2Ring



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!