2

I have a JSON file named 'students.json' which is as follows:-

{
    "students": {
        "1":{
            "name": "Ricky",
            "marks": {
                "science": "90",
                "english": "50"
            }
        },
        "2":{
            "name": "Brad",
            "marks": {
                "science": "80",
                "english": "75"
            }
        }
    }
}

I want to update Brad's english marks to 85. All I have is the JSON file, a list of path to marks, and updated marks.

updated_marks = "85"
path_to_marks = ["students", "2", "marks", "english"]

I want to do something like this,

import json

updated_marks = "85"
path_to_marks = ["students", "2", "marks", "english"]

with open('students.json', 'r+') as f:
    json_data = json.load(f)
    value = json_data

    #TODO: code to update marks
    
    f.seek(0)
    f.write(json.dumps(json_data))
    f.truncate()
YASH JADHAV
  • 143
  • 2
  • 11
  • look at [this](https://stackoverflow.com/a/29217080/7540911) answer, it's pretty much what you are trying to do – Nullman Dec 16 '21 at 10:44

3 Answers3

3
def update(json, path, new_value):
    obj_ptr = json
    for key in path:
        if key == path[-1]:
            obj_ptr[key] = new_value
        obj_ptr = obj_ptr[key]

Call it from your code like this:

update(json_data, path_to_marks, updated_marks)
1

Since you use json.load to load the file back into a Python object via the default conversion table, you should get a dictonary in your case.

So you should be able to edit the data normally like in a dict, in your case:

json_data["students"]["2"]["marks"]["english"] = updated_marks

EDIT:

Since you want to make the call based on the path_to_english_marks list, you can do something like mentioned here from jjp.

from functools import reduce
from operator import getitem

def set_nested_item(dataDict, mapList, val):
    """Set item in nested dictionary"""
    reduce(getitem, mapList[:-1], dataDict)[mapList[-1]] = val
    return dataDict

key_lst = ["key1", "key2", "key3"]
value = "my_value"
d = {"key1": {"key2": {"key3": "some_value"}}}

d = set_nested_item(d, key_lst, value)

print(d)
# {'key1': {'key2': {'key3': 'my_value'}}}
0x4Dark
  • 214
  • 1
  • 3
  • 10
  • Values are not fixed in the list, they can change. For example, I can receive- ["students", "3", "marks", "science"]. In this case, I have to update the science marks of 3rd student. – YASH JADHAV Dec 16 '21 at 10:47
  • Ok, means you want to manipulate a value based on the list `path_to_english_marks`. If the structure makes sense, we leave aside for now. You actually only have to take the list as keys for the request. – 0x4Dark Dec 16 '21 at 10:52
-1

Save it directly

data['students']['2']['marks']['english'] = marks
Stefan
  • 17,448
  • 11
  • 60
  • 79