#Referencing a nested Dictionary return error on base 'Nil'

40 messages · Page 1 of 1 (latest)

honest garnet
#

I'm trying to get a list of all the item names from a JSON file in res://, which are formatted as an Array containing a dictionary, containing a dictionary of key value pairs of the names in different languages (Picture is attached). When I use print(json_as_dict[i]) it will print all the correct info. When I use print(json_as_dict[i]["LocalizedNames]) it will print all the correct info. When i use print(json_as_dict[i]["LocalizedNames"]["EN-US"]) it gives the error.

Full code:

extends OptionButton

func _ready():
    var file = "res://Assets/items/items.json"
    var json_as_text = FileAccess.get_file_as_string(file)
    var json_as_dict = JSON.parse_string(json_as_text)
    traverse_array(json_as_dict)
    
func traverse_array(json_as_dict):
    if json_as_dict:
        for i in range(0, json_as_dict.size()):
                      //print(json_as_dict[i])    #Working
                      //print(json_as_dict[i]["LocalizedNames"]    #Working
            print(json_as_dict[i]["LocalizedNames"]["EN-US"])   //#Not working

I've tried a lot of stuff but I can't seem to figure out why it's not working even after some research and help in the beginner chat.

spare schooner
#

This is really strange. The error it’s printing doesn’t make sense if it prints out localized names. I wonder why it’s saying that’s null in this case. Are you sure this is the correct way to index a dictionary inside a dictionary?

I’m sure there’s an easier way to do this. Have you tried using a custom resource?

honest garnet
#

Im relatively new so I don't know what a custom resource is and at least from my experience with js this is how you'd reference nested objects and arrays, although I struggled for a long time because I expected doing json_to_dict[0][2][0] would do what I wanted but alas that is not the case so i had to fight with that until I realized it wanted the name of the object not it's position in the dictionary

terse hill
#

@honest garnet
Try in your function, the part of range, add to the size -1. Range(0, json_as_dict.size()-1).

honest garnet
#

I forgot to add that in after all the refactoring i tried but thank you. Still the same error

terse hill
#

Hmmm, try a print before in your ready to check if the dictionary is valid.

honest garnet
#

seems to be working fine

terse hill
#

Yup 👍

#

Ok, try in traverse to print off i only...

honest garnet
#

Here is i

#

This is json[i]

#

This is json[i][LocalizedNames]

terse hill
#

Ok, I'm not on com, and I think what you have to do is....

#

First you want to get a dictionary in a dictionary right?

honest garnet
#

It's an array containing a dictionary within a dictionary yes

#

I can get the array and the primary dictionary, just not the secondary one

terse hill
#

So you need to get that dictionary first, and I think you have to reference it like this. Give me a second to type out....

#

var tempDict: dictionary = json_as_dict[i]["LocalizedNames"]

print(tempDict["EN-US"])

#

On mobile so coding is weird....

#

Put that in the loop

honest garnet
terse hill
#

Does it print some of the variables off or stopped without any?

honest garnet
#

it didnt print anything, it crashed at the line trying to assign it to a new dictionary

terse hill
#

Ok

#

It's weird because you verified the json, and you verify all the elements in it until you get to the dictionary inside..... You see in the editor that it says it's null.... In your remote scene, you can check in there to see if you can check through it. Load it without the print so it won't error on you.

honest garnet
#

Im gunna have to come back to this tomorrow it's late. I'll try that in the morning thank you

terse hill
#

Yeah, I'll be on the com tomorrow if you don't have it figured out. I have to look through my code, but I think there's a convoluted way of getting it.

honest garnet
#

would it just be easier to refactor the data so the names arent nested?

terse hill
#

It may be easier, but then you may find your code is longer.

#

You can work through this or we will with you. Someone if not me can solve this.

ivory path
#

just a shot in the dark but could there be something going on with the "-" character here?

sacred willow
#

This error kinda looks like there's an entry somewhere in the file that is missing the "LocalizedNames" entry. If that's the case, try adding an additional if not null check before each step as you traverse the json structure. Just like the initial if json_as_dict: check.

I.e.
'''
Var localization_entry: Dictionary = json[i]
If localization_entry:
Var localized_names: Dictionary = localization_entry["LocalizedNames"]
If localized_names:
// etc
'''

Sorry for formatting, on mobile

ivory path
sacred willow
#

Ya, I imagine it'd print out all the ones that were valid until it hit the invalid one. That still might be happening here - from the screenshot, it looks like it opened to display the error in the stack trace tab, but it would've printed out in the Errors tab, I think, so it's really easy to miss that it's there.

spare schooner
spare schooner
terse hill
#

@honest garnet

func _ready():
    var dictArray: Array = []
    var dict1: Dictionary = {}
    var dict2: Dictionary = {}
    var dictInfo: Dictionary = {}
    
    dict1["DictContainer"] = {}
    dict2["AnotherContainer"] = {}
    
    dictInfo["ContainedInformation"] = "I have been contained..."
    dict2["AnotherContainer"] = dictInfo
    
    dict1["DictContainer"] = dict2
    dictArray.append(dict1)
    print(dictArray[0]["DictContainer"]["AnotherContainer"]["ContainedInformation"])
honest garnet
#

Thank you everyone who helped, the dataset did indeed include a relatively low number of "LocalizedNames": null which caused it to throw a fit. I've simply thrown in a check that the name is not null. Probably would've caught it sooner if the dataset wasn't 350k lines 😅

terse hill
#

AWESOME!

#

By the way, I knew you could do it, great job. You can mark the issue solved.