pythonjsondictionarynested-json

Insert/Add a json object in a dictionary at nested level dynamically


I am working on a script to generate some test data based on a json spec. The intention of this script is to construct a json object/python dict record

To simplify things, I am using a list items here that represents my source items, which also represent the path where the value should be inserted.

Here's my intended output -

{
    "access": {
        "device": {
            "java": {
                "version": "Test Data"
            },
            "python": {
                "version": "Test Data"
            }
        },
        "type": "Test Data"
    },
    "item1": 1,
    "item2": 0
}

I am able to build the nested objects but they are all getting inserted at first level of the dictionary instead.

How can I use dest_path to store the result in the intended location?

Source:

import json
import random

def get_nested_obj(items: list):
    """
    Construct a nested json object
    """
    
    res = 'Test Data'

    for item in items[::-1]:
        res = {item: res}

    return res

def get_dest_path(source_fields):
    """
    Construct dest path where result from `get_nested_obj` should go
    """

    dest_path = ''

    for x in source_fields:
        dest_path += f'[\'{x}\']'
    
    return 'record'+dest_path

record = {}
items = ['access.device.java.version', 'access.device.python.version', 'access.type', 'item1', 'item2']

for item in items:
    if '.' in item:
        source_fields = item.split('.')

        temp = record
        for i, source_field in enumerate(source_fields):
            if source_field in temp:
                temp = temp[source_field]
                continue

            res = get_nested_obj(source_fields[i+1:])

            dest_path = get_dest_path(source_fields[:i])
            print(dest_path)

            record[source_field] = res # Here's the problem. How to use dest_path here?
            break
    else:
        record[item] = random.randint(0, 1)
            
print(json.dumps(record))

My output:

{
    "access": {
        "device": {
            "java": {
                "version": "Test Data"
            }
        }
    },
    "python": {
        "version": "Test Data"
    },
    "type": "Test Data",
    "item1": 1,
    "item2": 0
}

Solution

  • To construct the record dictionary from the items list you can use next example:

    import random
    
    record = {}
    items = [
        "access.device.java.version",
        "access.device.python.version",
        "access.type",
        "item1",
        "item2",
    ]
    
    for i in items:
        i = i.split(".")
    
        if len(i) == 1:
            record[i[0]] = random.randint(0, 1)
        else:
            r = record
            for v in i[:-1]:
                r.setdefault(v, {})
                r = r[v]
            r[i[-1]] = "Test Data"
    
    print(record)
    

    Prints:

    {
        "access": {
            "device": {
                "java": {"version": "Test Data"},
                "python": {"version": "Test Data"},
            },
            "type": "Test Data",
        },
        "item1": 1,
        "item2": 1,
    }