-1

I want to change the value of a nested key but I get this error

key['score'] = new_score # come back to this
 TypeError: 'str' object does not support item assignment

Here is my code:

def add_score(self, obj):
        for child in reversed(self.root.screen_two.ids.streak_zone.children):
            name = child.text

            with open("streak.json", "r+") as read_file:
                data = json.load(read_file)

            for key in data.keys():
                if key == name:
                    score = data.get(key, {}).get('score')
                    new_score = score + 1
                    key['score'] = new_score # come back to this

This is what my json file looks like:

{"one": {"action": "one", 
        "delay": 1557963534.4314187, 
        "seconds": 60, 
        "score": 0, 
        "delta": 1557963474.4314187}, 
 "two": {"action": "two", 
         "delay": 1557963664.037102, 
         "seconds": 120, 
         "score": 0, 
         "delta": 1557963544.037102}, 
 "three":{"action": "three", 
          "delay": 1557963792.4683638, 
          "seconds": 180, 
          "score": 0, 
          "delta": 1557963612.4683638}
}

How would I change the score value inside of my json file?

al76
  • 754
  • 6
  • 13
yemi.JUMP
  • 313
  • 2
  • 12

3 Answers3

0

You should be able to update the dictionary element directly.

Replace the following

for key in data.keys():
    if key == name:
        score = data.get(key, {}).get('score')
        new_score = score + 1
        key['score'] = new_score # come back to this

with

data[name]['score'] += 1

So code would be

def add_score(self, obj):
        for child in reversed(self.root.screen_two.ids.streak_zone.children):
            name = child.text

            with open("streak.json", "r+") as read_file:
                data = json.load(read_file)

            data[name]['score'] += 1
al76
  • 754
  • 6
  • 13
  • I need to keep the `if key == name:` protion of the code because the program wont know what `key` is and when I make my code: `key[name]['score'] += 1` I get `TypeError: string indices must be integers` – yemi.JUMP May 16 '19 at 01:06
  • Just confirming you replaced the 5 lines with my suggested fix? – al76 May 16 '19 at 01:16
  • when I do that I get ` NameError: name 'key' is not defined` – yemi.JUMP May 16 '19 at 01:20
  • apologies, typo at my end. I've updated the answer to use data not key – al76 May 16 '19 at 01:23
  • The value of `score` in my json file still doesn't change. – yemi.JUMP May 16 '19 at 01:35
  • You need to write the updated dictionary back to the file. You can confirm the dictionary is updated with print data[name]['score'] https://stackoverflow.com/questions/12309269/how-do-i-write-json-data-to-a-file – al76 May 16 '19 at 01:42
0

In your for loop, you are iterating over keys array which is ['one','two','three'] in your case.

Try below code. Hope this will help!

for key,value in data.items():
    if key == name:
        score = value['score']       
        new_score = score + 1
        value['score'] = new_score 

Or for one liner instead of for loop use below,

data[name]['score']+=1  #name='one'

Edit within file

with open('streak.json', 'r+') as f:
    data = json.load(f)
    data[name]['score']+=1 
    f.seek(0)
    json.dump(data, f, indent=4)
    f.truncate()  
bkyada
  • 332
  • 1
  • 9
  • The value of `score` in my json file doesn't change. – yemi.JUMP May 16 '19 at 01:32
  • @yemi.JUMP That is because you are reading/parsing the JSON file and storing data into a variable and after that performing operation on that variable not in the file. – bkyada May 16 '19 at 01:35
  • Sorry if I wasn't clear with my question. I have edited my post to include that I want the file to change. – yemi.JUMP May 16 '19 at 01:38
  • Your original question and code supplied didn't mention writing to a file. – al76 May 16 '19 at 01:53
  • @bkyada although this method works, every value with the name score is changed. Is there a way to only have one `score` change? – yemi.JUMP May 17 '19 at 00:12
  • @yemi.JUMP Can you be more clear about the use case? If you can provide an example. Here, your outer loop is getting all the names and based on comparison it is updating the score. To change one `score` change do you have any other requirement to check? – bkyada May 17 '19 at 16:41
  • The name of the key is the same as the name of the button, that’s why I did `name=child.text` but it’s updating all of the buttons. – yemi.JUMP May 18 '19 at 13:10
0

This should work

with open("a.json", "r+") as read_file:
    data = json.load(read_file)
    data[name]['score'] += 1 # update score

with open("a.json", "w") as json_file: #write it back to the file
    json.dump(data, json_file)
Nithin
  • 1,065
  • 8
  • 15