How to generate a dictionary from a json parsed result?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Dostoi

TL;DR: How to convert a parsed json string to a godot.Collections.Dictionary? In other words, why this returns a “null” value?

var dict = JSON.Parse(savedGame.GetAsText()).Result as Godot.Collections.Dictionary;

Detailed version: All the variables in my game are stored in a single dictionary that looks like that:

gamevariables = new Godot.Collections.Dictionary
        {
            { "variable_A", false},
            { "variable_B", false},
            { "variable_etc", true}
        }

I can then successfuly store these value to a text file like that:

var savedData = _gameVariables.gamevariables.ToString();
        var savedGame = new File();
        savedGame.Open("user://save_example_slot_1.save", File.ModeFlags.Write);
        savedGame.StoreLine(JSON.Print(savedData));
        savedGame.Close();

This correctly creates the file containing the following text:

"{variable_A:False, variable_B:False, variable_etc:True}"

And now, where the troubles begin. What I’m trying to do is basicaly overwrite the base dictionary named “gamevariables” in this example, by the one that I saved (with variables which might have different value from before). So I do that:

    var savedGame = new File();
    savedGame.Open("user://save_example_slot_1.save, File.ModeFlags.Read);
    JSONParseResult dict = JSON.Parse(savedGame.GetAsText());
    savedGame.Close();

And if I add:

    GD.Print(_gameVariables.gamevariables);
    GD.Print(dict.Result);

It returns the exact same structures of text:

{variable_A:False, variable_B:False, variable_etc:True}
{variable_A:False, variable_B:False, variable_etc:True}

Yet, they are of different types as the next experiment proves:

    GD.Print(_gameVariables.gamevariables.GetType());
    GD.Print(dict.Result.GetType());

Which returns:

    Godot.Collections.Dictionary
    System.String

But since they have the same structure, I though it would be possible to cast the System.String one as a Godot.Collections.Dictionary. So here’s what I did:

var dict2 = dict.Result as Godot.Collections.Dictionary;

which doesn’t works since it returns “null”. Moreover, which indicates that the conversion, somehow, failed, trying to returns a value from “GD.Print(dict2.GetType());” crashes the game. Which, I think, indicate some sort of “invalid” type.

So, what am I misunderstanding to be able to load a string of text stored in a text file as a dictionary?

Thank you for your time.

https://www.youtube.com/watch?v=g_7hgbxjtLY

Landroval | 2023-02-12 16:26

:bust_in_silhouette: Reply From: Inces

You just have to retranslate variables back to their types, as everything imported from JSON will always be a String. You can do it manually, like :

var a = bool(saveddata[a])
var b = int(saveddata[b])

but there is better way. When saving use var2str(a) and upon loading use str2var(a)
Be careful though, integers may eventually become floats like this

something like that?

To save:

savedGame.StoreLine(JSON.Print(GD.Var2Str(saveData)));

Then, when loading:

public Dictionary dictionary;

public void some_method_to_load()
    {
        dictionary = (Godot.Collections.Dictionary)GD.Str2Var(data);
    }

If my construction isn’t incorrect (which I hope it is), it returns the exact same error (IE: specified cast is not valid)

Dostoi | 2022-05-31 19:28

I am afraid it is a bit more tedious. You need to iterate through gamevariables entries and store each value with var2str() as JSON line. Lets make it easier first. If all of your variables are booleans, than all You need to do is just something like this on loading :

for key in Parsingresult.keys() :
       gamevariables[key] = bool(Parsingresult[key])

If your dict contains varying data types, it might be easier to convert them with var2str into JSON lines on saving, so using str2var on loading will automatically assign their original type.

Edit : I actually don’t use C+, I hope it is universal advice

Inces | 2022-05-31 19:47

Alright. It was indeed a little tedious because of… well, C# and lack of knowledge.

Actually var saveData = JSON.Parse(saveGame.GetLine()).Result returned indeed something of a type “Godot.Collections.Dictionary”. But, for a reason beyond my knowledge, it is, somehow, not a usable one. It is, in C#, if I understood correctly, technically only an “object”. For a string in a file parsed as JSON, to become a usable dictionary, you have to write:

var saveData = JSON.Parse(saveGame.GetLine()).Result as Godot.Collections.Dictionary;

Thank you for your time, Inces. I’ll check that answer as “best answer”, for it is, since, from what I saw, your answer is the detailed method to create a dictionary from a JSON file in gdscript. Moreover, I hope that people looking for answer in C# would read the comments.

Thank you again :slight_smile:

Dostoi | 2022-06-01 16:31