0

The problem

I have a few JSON Files which are built different and I need a code to be able to edit a value as well in the dicts which are just one dict and others who have nested dicts without removing other values.

Examples

So I got for example one JSON File which is like this:

JSON/id_list.json

{"whatever": [ID_1, ID_2, ID_3]}

JSON/main_id.json

{"value": "yes"}

or another on like this

JSON/id_data.json

{"data": {"ID_1": {"type1": 0, "type2": 1}, "ID_2": {"type1": 0, "type2": 0}}}

Current Code

My current code is only able to edit the first and / or second so I wanted it to be general but just didn't seem to find an answer

Functions/get_json.py

def get(name: str, path: str, load: bool):
    if load:
        _load(path)
    return loadedf[name]

def update(name: str, text, path: str, load: bool):
    if load:
        _load(path)
    loadedf[name].remove(get(name, path, False))
    loadedf[name].append(text)

    with open(path, "w+"):
        json.dump(loadedf, nfl)

def _load(path: str):
    preloadf = open(path, 'r')
    global loadedf
    loadedf = json.load(preloadf)

game.py

from Functions import get_json.py
async def random_function():
    get_json.get('whatever', '/JSON/id_list.json', True)
    get_json.update('value', 'no', '/JSON/main_id.json', True)

New Code Idea

game_new.py

from Functions import get_json.py
async def random_function():
    get_json.get(['whatever'], '/JSON/id_list.json', True)
    get_json.get(['data', 'ID_1', 'type2'], '/JSON/id_data.json', True)
    get_json.update(['data', 'ID_2', 'type1'], '/JSON/id_data.json', False)

But I have no Idea how to do or realize this.

What I tried so far

I tried dict.update(), doing it with for loops like

prev = loadedf
for i in name:
    prev = prev[i]

    prev.remove(get(name, path, False)[0])

or with some weird stuff like __setattr()__ and with a way with which I wasn't happy as it can't handle JSONs generally and was really long and complicated;

I tried to do it with the optional parameters deep, name2 and name3 and do it with an if elif to do if deep == 2: return loadedf[name][name2].


The code used here might be outdated from what I had or partly not working as I wrote it completely new because I rewrote it a few times to reach my goal; to be generally able to do all this with JSON Files.

FileX
  • 773
  • 2
  • 7
  • 19
  • If the scope of the problem you're facing limited to updating the dictionary returned by `json.load`, perhaps this is a duplicate of [this question](https://stackoverflow.com/questions/3232943/update-value-of-a-nested-dictionary-of-varying-depth). – jisrael18 Dec 22 '21 at 16:49
  • tested it in a few cases and "prereleased" it for my discord bot and the result was that now stuff is happening which I couldn't even explain and I still can't update one value without removing the other values from the dict – FileX Dec 23 '21 at 22:30
  • Generally you should use JSON solely as an I/O format. You should transform the objects into instances of user-defined classes otherwise (if you have a schema this can be done easily). – o11c Dec 23 '21 at 22:39

1 Answers1

0

Got an Idea yesterday evening and built it in to get this working code

def edit_json(name: list, text, path: str, load: bool, execute: str):
    try:
        if load:
            _load(path)

        prev = "loadedf"
        for entry in name:
            if isinstance(entry, int):
                prev += f"[{entry}]"
            else:
                prev += f"[\"{entry}\"]"

        if execute == "add" or execute == "append":
            exec(prev + ".append(text)")
        elif execute == "remove":
            exec(prev + ".remove(text)")
        elif execute == "update":
            exec(prev + " = text")

        with open(path, "w+") as nfl:
            json.dump(loadedf, nfl)

So this is now my solution also with the idea of having name as an array built in

FileX
  • 773
  • 2
  • 7
  • 19