Reading a JSON string | TypeError: string indices must be integers

62,107

Solution 1

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

Solution 2

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)

Solution 3

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

Share:
62,107
Billy Dawson
Author by

Billy Dawson

Updated on November 27, 2020

Comments

  • Billy Dawson
    Billy Dawson over 3 years

    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()
    
  • Vincent Beltman
    Vincent Beltman over 9 years
    @Rawing You mean in mhello right? Cause _getCurrentOperator already gets it by parameter.
  • Vincent Beltman
    Vincent Beltman over 9 years
    OK TY Will edit. I'm always using OOP so I'm not familiar with global.
  • Billy Dawson
    Billy Dawson over 9 years
    Thanks for the reply! Having made these changes I'm still experiencing the exact same error
  • Aran-Fey
    Aran-Fey over 9 years
    @BillyDawson: Did you add global data at the top of the readText function?
  • Billy Dawson
    Billy Dawson over 9 years
    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.
  • Aran-Fey
    Aran-Fey over 9 years
    @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.
  • Billy Dawson
    Billy Dawson over 9 years
    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 :)
  • Robin
    Robin over 6 years
    "It seems that your code is expecting data to be a dictionary." +1
  • Vincent Beltman
    Vincent Beltman over 2 years
    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.