- Home /
Deserializing dictionary with 'Json.Net' for Unity returns a null object.
I'm using the Json.Net pluggin for unity which adds support for Vectors and Matrices to standard Newtonsoft.Json but for what I'm doing only knowledge of default json.net (Newtonsoft.Json) should be relevant.
This json object contains a list of Person object which each have a dictionary on them.
{
"$type": "PeopleDataObject, Assembly-CSharp",
"People": {
"$type": "System.Collections.Generic.List`1[[Person, Assembly-CSharp]],
mscorlib",
"$values": [
{
"$type": "Person, Assembly-CSharp",
"Id": 0,
"FirstName": "Daffy",
"LastName": "Duck",
"Age": 0,
"Sex": true,
"Stats": {
"$type": "System.Collections.Generic.Dictionary`2[[System.String,
mscorlib],[System.Int32, mscorlib]], mscorlib",
"str": 9,
"dex": 13,
"con": 9,
"int": 13,
"wis": 10,
"cha": 8
}
},
{
"$type": "Person, Assembly-CSharp",
"Id": 1,
"FirstName": "Wilma",
"LastName": "Flintstone",
"Age": 0,
"Sex": false,
"Stats": {
"$type": "System.Collections.Generic.Dictionary`2[[System.String,
mscorlib],[System.Int32, mscorlib]], mscorlib",
"str": 7,
"dex": 9,
"con": 9,
"int": 12,
"wis": 12,
"cha": 12
}
}
]
},
"Count": 2
}
I checked that the string read doesn't come out malformed by writing the it to another file so I know that everything serializes correctly but on deserialization the dictionaries are lost so that when I go to use it or save it again they're null. The debugger identifies it as a null object. The code below follows the documentation for general objects but I couldn't find a specific case for objects containing dictionaries. I made sure to include TypeNameHandling so as to try to make sure it knew to deserialize into a dictionary but I'm not getting that result.
private void LoadRoster()
{
string path = Path.Combine(Application.streamingAssetsPath, "PeopleData.json");
string debug = Path.Combine(Application.streamingAssetsPath, "debug.json");
if (!File.Exists(path))
{
Debug.Log("NO SAVE FILE RECOGNISED");
}
else
{
PeopleDataObject allPeople = PeopleDataObject.Instance;
string jsonString = File.ReadAllText(path);
//check that the file is read correctly
File.WriteAllText(debug, jsonString);
allPeople = JsonConvert.DeserializeObject<PeopleDataObject>(jsonString, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
});
People = allPeople.People;
Person.AllTimeCount = allPeople.Count;
Debug.Log("Loaded");
}
}
It's trying to deserialize to the following PeopleDataObject class which itself contains a list of Person which I will also provide below.
PeopleDataObject:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PeopleDataObject
{
//<Singleton Boilerplate>
private static PeopleDataObject instance = null;
private static readonly object padlock = new object();
PeopleDataObject() {}
public static PeopleDataObject Instance
{
get
{
lock(padlock)
{
if (instance == null)
{
instance = new PeopleDataObject();
}
return instance;
}
}
}
//</Singletone Boilerplate>
public List<Person> People { get; set; }
public int Count { get; set; }
}
Person:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Person
{
public int Id { get; private set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; private set; }
public bool Sex { get; private set; } //true = male, false = female
public Dictionary<string, int> Stats { get; private set; }
public static int AllTimeCount { get; set; }
private GameObject messageController;
public Person(string first, string last, bool sex, GameObject controller)
{
Debug.Log(" overload 1");
FirstName = first;
LastName = last;
Age = 0;
Sex = sex;
Id = AllTimeCount;
AllTimeCount++;
if (controller != null)
messageController = controller;
else
messageController = GameObject.Find("PersonManager");
//if sex is true (male) colour modifier is blue, else colour modifier is pink
string colourMod = sex ? "#4286f4" : "#ff56ff";
Notification(string.Format("<{0}>{1} {2}</color> was born. ", colourMod, first, last));
}
public Person(int id, string first, string last, bool sex, Dictionary<string, int> stats)
{
Debug.Log("overload 2");
Id = id;
FirstName = first;
LastName = last;
Sex = sex;
Stats = stats;
}
public Person()
{
Debug.Log("overload 3");
}
public void SetStats(Dictionary<string, int> s)
{
Stats = s;
}
public void IncrementAge()
{
Age++;
}
public void Notification(string message)
{
MessageController controller = messageController.GetComponent<MessageController>();
controller.PostMessage(message);
}
}
By the way I am aware that messageController in Person is null when constructors 2 or 3 are used but that's not my concern right now and it has no bearing on the current issue but it will be seen to.
I've been stuck on this for some time. I already know I'm an idiot but I'd much appreciate a helping hand to tell me why I'm an idiot.
Cheers, Dan