How to save and load an array of dictionaries to a file?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By CowThing
:warning: Old Version Published before Godot 3 was released.

I have an array with dictionaries in it, each dictionary is a different item. I’m trying to save and load this inventory. The file is saving correctly, and when I load the file I have a print() which is printing the correct value from the line it’s reading. However after all the items have been appended, the inventory is just full of whatever item was in the last slot.
For example if I save an inventory with item A, item B, and item C. After loading the inventory would be 3 duplicates of item C.

This is my code:

func save_game():
	var savegame = File.new()
	savegame.open("user://savegame.save", File.WRITE)
	
	for i in range(inventory.size()):
		var data = inventory[i]
		savegame.store_line(data.to_json())
	
	savegame.close()


func load_game():
	var savegame = File.new()
	if !savegame.file_exists("user://savegame.save"):
		return
	
	var current_line = {}
	savegame.open("user://savegame.save", File.READ)
	while(!savegame.eof_reached()):
		var line = savegame.get_line()
		if line.empty():
			break
		
		current_line.clear()
		current_line.parse_json(line)
		print(current_line) #this is printing the correct value
		inventory.append(current_line) #this is not appending the correct value
	
	savegame.close()

I had a similar problem with a dictionary of dictionaries. See my related question and the answers on reddit here

duke_meister | 2016-03-29 05:44

:bust_in_silhouette: Reply From: batmanasb

I never used json before, but maybe you are parsing it wrong. I’d suggest trying the easy method and just use store_var and get_var to store the entire array of dictionaries at once.

fixed, woops… put_var was for packets not files

I didn’t think of that, I was just following the tutorial on the Godot Docs. But this works, thank you. Also it’s store_var instead of put_var.

I’m still unsure why my original method wasn’t working.

CowThing | 2016-03-28 23:33

:bust_in_silhouette: Reply From: Bojidar Marinov

The problem is that Dictionary, Array and Reference classes are passed by reference, and not by value. Since Dictionary::parse_json would edit the same dictionary in-place, you would add three reference to the same Dictionary.

There are two ways to workaround this.
The first one would be to move the declaration of current_line inside the loop.
The second would be to use the Dictionary copy constructor, like so:

inventory.append(Dictionary(current_line))

I liked the last option but it doesn’t seem to do the trick in my similar case. Placing current_line within the loop did however.

duke_meister | 2016-03-29 10:30

@duke_meister It is quite probable that I messed something up, since I didn’t test it. Maybe if somebody else confirms, I’ll change it.

Bojidar Marinov | 2016-03-29 12:27