Failing to load List within a Dictionary<string, object>

Discussion and help for Easy Save 3
Post Reply
robotSmith
Posts: 39
Joined: Thu Apr 01, 2021 4:53 pm

Failing to load List within a Dictionary<string, object>

Post by robotSmith »

Hello!

I started trying to save using generic objects, and when I'm saving a Dictionary<string, object>, and I'm adding a List as an object it fails as

Code: Select all

FormatException: Expected '{' or "null", found '['.
. So far, I'm not having issues with any other type, but only Lists (I have not tried any other collections). I'm using Version 3.4.2 on Unity 2021.3.0f1.

Basically:

Code: Select all

    List<string> thisIsAList = new List<string> { "One", "Two" };
    Dictionary<string, object> references = new Dictionary<string, object>();

    public void SomeSaveMethod()
    {
        references.Add("List", thisIsAList);
        ES3.Save("References", references);
    }

    public void SomeLoadMethod()
    {
        references = ES3.Load<Dictionary<string, object>>("References");
        thisIsAList = (List<string>)references["List"];
    }
Result: FormatException: Expected '{' or "null", found '['.

I saw the same issue here but the poster did not follow through https://moodkie.com/forum/viewtopic.php?p=9529#p9529.
Is there anything that you think I can to overcome this?

Thank you in advance!
robotSmith
Posts: 39
Joined: Thu Apr 01, 2021 4:53 pm

Re: Failing to load List within a Dictionary<string, object>

Post by robotSmith »

I think I found the issue on what's going on on the save file, however, I'm not sure where the change would go on the code.

So if I save the code above, I will get this on the SaveFile.es3:

Code: Select all

"References" : {
		"__type" : "System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]],mscorlib",
		"value" : {"strings":[
				"One","Two"
			]

		}
	},
From saving the other types, I noticed that ES3 appends the cast like: "__type" : "string""Hello", but that's not happening on Collections (I tried with an array too), there is no casting. I tried replicating that same approach by modifying the Save file, and when loading it works correctly. So this is what worked:

Code: Select all

"References" : {
		"__type" : "System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]],mscorlib",
		"value" : {
			"strings":{
				"__type" : "System.Collections.Generic.List`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]],mscorlib"[
					"One","Two"
				]
			},
		}
	}
User avatar
Joel
Moodkie Staff
Posts: 4826
Joined: Wed Nov 07, 2012 10:32 pm

Re: Failing to load List within a Dictionary<string, object>

Post by Joel »

Hi there,

Because you're using 'object' rather than a strict type for Dictionary items, there is not enough type information to determine the type of the object you're loading from your Dictionary.

Your modified file works because you've wrapped it in an object which provides this type information. In your case you would need to save a List wrapped in an object rather than the List itself to be able to load it as an object. I.e.

Code: Select all

public class ListWrapper
{
	public List<string> myList;
}
However, if your Dictionary only contains List<string>, you should use Dictionary<string, List<string>> so that it is strictly typed.

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
robotSmith
Posts: 39
Joined: Thu Apr 01, 2021 4:53 pm

Re: Failing to load List within a Dictionary<string, object>

Post by robotSmith »

Perfect! It worked out with the object wrapper.

The Dictionary contains many other types so I cannot strictly type it, basically, I let a component save and load any information they want about themselves. Before I was defining the types, but it has been hard to scale.

I created a generic wrapper with implicit conversions to make it easy on me. Thanks for your help as always :) !!!

Code: Select all

public class GenericListWrapper<T>
{
    [ES3Serializable]
    private List<T> myList = new List<T>();

    public List<T> MyList { get => myList; set => myList = value; }

    public static implicit operator List<T>(GenericListWrapper<T> wrapper)
    {
        return wrapper.MyList;
    }

    public static implicit operator GenericListWrapper<T>(List<T> list)
    {
        GenericListWrapper<T> newWrapper = new GenericListWrapper<T>();
        newWrapper.myList = list;
        return newWrapper;
    }
}
User avatar
Joel
Moodkie Staff
Posts: 4826
Joined: Wed Nov 07, 2012 10:32 pm

Re: Failing to load List within a Dictionary<string, object>

Post by Joel »

Glad that was helpful :)

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
Post Reply