0

This is an example of a JSON database that I will work with in my Python code.

{
  "name1": {
    "file": "abc"
    "delimiter": "n"
  },
  "name2": {
    "file": "def"
    "delimiter": "n"
    }
}

Pretend that a user of my code presses a GUI button that is supposed to change the name of "name1" to whatever the user typed into a textbox.

How do I change "name1" to a custom string without manually copying and pasting the entire JSON database into my actual code? I want the code to load the JSON database and change the name by itself.

martineau
  • 119,623
  • 25
  • 170
  • 301
  • 1
    When you say "load the JSON database", are you working with JSON text and want to try to keep it that way or are you loading the JSON text into a python dict? If you are working with a dict, do you care if the dict is reordered as a result? – JonSG May 21 '21 at 23:55
  • I'm not sure what's the difference between keeping a JSON as text or loading it into a dict. Is any one method better than the other? If I am working with a dict, I do NOT care if the dict is reordered as a result. I'm assuming that by "reorder" you mean the attribute "name1" and "name2" could switch positions but keep their respective "file" and "delimiter" attributes. – John Smith May 25 '21 at 18:22
  • If you don't care if you have json text or a dict and don't care about ordering of keys then I recommend the answer by norbert-tiborcz as something quick and dirty or if you want something more robust, the answer by @martineau. If you need to preserve key order or work strictly with text then there are alternate strategies as well. – JonSG May 25 '21 at 19:25

3 Answers3

1

You can use the object_hook parameter that json.loads() accepts to detect JSON objects (dictionaries) that have an entry associated with the old key and re-associate its value with new key they're encountered.

This can be implement as a function as shown follows:

import json

def replace_key(json_repr, old_key, new_key):

    def decode_dict(a_dict):
        try:
            entry = a_dict.pop(old_key)
        except KeyError:
            pass  # Old key not present - no change needed.
        else:
            a_dict[new_key] = entry
        return a_dict

    return json.loads(json_repr, object_hook=decode_dict)


data = '''{
              "name1": {
                  "file": "abc",
                  "delimiter": "n"
              },
              "name2": {
                  "file": "def",
                  "delimiter": "n"
              }
          }
       '''

new_data = replace_key(data, 'name1', 'custom string')
print(json.dumps(new_data, indent=4))

Output:

{
    "name2": {
        "file": "def",
        "delimiter": "n"
    },
    "custom string": {
        "file": "abc",
        "delimiter": "n"
    }
}

I got the basic idea from @Mike Brennan's answer to another JSON-related question How to get string objects instead of Unicode from JSON?

martineau
  • 119,623
  • 25
  • 170
  • 301
0

Load the JSON object into a dict. Grab the name1 entry. Create a new entry with the desired key and the same value. Delete the original entry. Dump the dict back to your JSON file.

This is likely not the best way to perform the task. Use sed on Linux or its Windows equivalent (depending on your loaded apps) to make the simple stream-edit change.

Prune
  • 76,765
  • 14
  • 60
  • 81
0

If I understand clearly the task. Here is an example:

import json

user_input = input('Name: ')

db = json.load(open("db.json"))
db[user_input] = db.pop('name1')
json.dump(db, open("db.json", 'w'))
Norbert Tiborcz
  • 306
  • 2
  • 9