14

I'm trying to create a program that will read in a JSON string through the GUI and then use this to perform additional functions, in this case breaking down a mathematical equation. At the moment I am getting the error:

"TypeError: string indices must be integers"

and I have no idea why.

The JSON I am trying to read in is as follows:

{
"rightArgument":{
"cell":"C18",
"value":9.5,
"type":"cell"
},
"leftArgument":{
"rightArgument":{
"cell":"C3",
"value":135,
"type":"cell"
},
"leftArgument":{
"rightArgument":{
"cell":"C4",
"value":125,
"type":"cell"
},
"leftArgument":{
"cell":"C5",
"value":106,
"type":"cell"
},
"type":"operation",
"operator":"*"
},
"type":"operation",
"operator":"+"
},
"type":"operation",
"operator":"+"
}
import json
import tkinter
from tkinter import *

data = ""
list = []

def readText():
    mtext=""
    mtext = strJson.get()
    mlabel2 = Label(myGui,text=mtext).place(x=180,y=200)
    data = mtext

def mhello():
    _getCurrentOperator(data)

def _getCurrentOperator(data):
    if data["type"] == "operation":

        _getCurrentOperator(data["rightArgument"])        
        _getCurrentOperator(data["leftArgument"]) 
        list.append(data["operator"])
    elif data["type"] == "group":
        _getCurrentOperator(data["argument"]) 
    elif data["type"] == "function":
        list.append(data["name"]) # TODO do something with arguments
        for i in range(len(data["arguments"])):
            _getCurrentOperator(data["arguments"][i])
    else:
        if (data["value"]) == '':
            list.append(data["cell"])
        else:
            list.append(data["value"])

print(list)

myGui = Tk()
strJson = StringVar()


myGui.title("Simple Gui")
myGui.geometry("400x300")

label = Label(text = 'Welcome!').place(x=170,y=40)
btnStart = Button(myGui,text='Start',command=mhello).place(x=210,y=260)
btnRead = Button(myGui,text='Read text',command=readText).place(x=210,y=200)
txtEntry = Entry(myGui, textvariable=strJson).place(x=150,y=160)
btnOptions = Button(myGui, text = "Options").place(x=150,y=260)

myGui.mainloop()
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Billy Dawson
  • 149
  • 1
  • 1
  • 5
  • Could you give the whole stacktrace? – Vincent Beltman Jan 08 '15 at 11:37
  • Hi, thanks for the reply :) Whilst running the program, the Call Stack window remains empty – Billy Dawson Jan 08 '15 at 11:42
  • The question should have originally been closed, if not as a duplicate, then due to lacking an appropriate [mre]. It's also important to try to [debug](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) code before posting a question. – Karl Knechtel Sep 08 '22 at 06:20

3 Answers3

19

You are never parsing the string to a dictionary (json object). Change data = mtext to: data = json.loads(mtext) You should also add global data to the readText method

Vincent Beltman
  • 2,064
  • 13
  • 27
  • @Rawing You mean in mhello right? Cause _getCurrentOperator already gets it by parameter. – Vincent Beltman Jan 08 '15 at 11:45
  • OK TY Will edit. I'm always using OOP so I'm not familiar with global. – Vincent Beltman Jan 08 '15 at 11:46
  • Thanks for the reply! Having made these changes I'm still experiencing the exact same error – Billy Dawson Jan 08 '15 at 11:48
  • @BillyDawson: Did you add `global data` at the top of the `readText` function? – Aran-Fey Jan 08 '15 at 11:49
  • I'd put global data at the start of the program rather than in readText. Having done this there are now no errors but the program doesn't output the broken down equation, nothing appears at all. – Billy Dawson Jan 08 '15 at 11:50
  • @BillyDawson: Why would you expect anything to "appear"? You're only appending stuff to your `list` variable. You aren't outputting anything, nor are you modifying the GUI. – Aran-Fey Jan 08 '15 at 11:53
  • I'd originally wanted the print(list) to output stuff for testing purposes, I've managed to fix that now by putting it in the right place. The code works perfectly now! Thanks guys :) – Billy Dawson Jan 08 '15 at 12:02
6

TypeError: string indices must be integers means an attempt to access a location within a string using an index that is not an integer. In this case your code (line 18) is using the string "type" as an index. As this is not an integer, a TypeError exception is raised.

It seems that your code is expecting data to be a dictionary. There are (at least) 3 problems:

  1. You are not decoding ("loading") the JSON string. For this you should use json.loads(data) in the readText() function. This will return the dictionary that your code expects elsewhere.
  2. data is a global variable with value initialised to an empty string (""). You can not modify a global variable within a function without first declaring the variable using the global keyword.
  3. The code builds a list by appending successive items to it, however, that list is not used elsewhere. It is printed after the definition of _getCurrentOperator() but this is before any processing has been done, hence it is still empty at that point and [] is displayed. Move print(list) to mhello() after_getCurrentOperator(). (BTW using list as a variable name is not advised as this shadows the builtin list)

You can revise readText() to this:

def readText():
    global data
    mtext=""
    mtext = strJson.get()
    mlabel2 = Label(myGui,text=mtext).place(x=180,y=200)
    data = json.loads(mtext)
mhawke
  • 84,695
  • 9
  • 117
  • 138
6

sometimes you need to use json.loads again.. this worked for me..

jsonn_forSaleSummary_string = json.loads(forSaleSummary)  //still string
jsonn_forSaleSummary        = json.loads(jsonn_forSaleSummary_string)

finally!! json

Brian Sanchez
  • 832
  • 1
  • 13
  • 11
  • I think what may be happening here is that your json is surrounded by quotes, while the quotes inside are escaped `"{\\"key\\":\\"value\\"}"`. In that case, the initial json.loads removes the surrounding quotes and the escape characters, leaving a json object. The second json.loads then parses the json object. – Vincent Beltman Aug 26 '21 at 07:36