XerShade XerShade - 28 days ago 12
C# Question

NewtonSoft.Json, Unable to deserialize a child dictionary in a dictionary

I am trying to deserialize a C#

Dictionary<string,object>
that contains a
Dictionary<string,bool>
as one of the entries. The code generates/serializes the file fine but when it goes to load it I get the following error.

Unable to cast object of type 'Newtonsoft.Json.Linq.JObject' to type 'System.Collections.Generic.Dictionary`2[System.String,System.Boolean]


Been trying to figure this out for a few hours now, and after much googling I can't seem to figure it out. The source files are a bit big so I will link them below instead of posting the full files.

The code is erroring on the return call in the Get function in this class,
https://gitlab.com/XerShade/Esmiylara.Online/blob/alpha-2-dev/source/Esmiylara.Frameworks/ConfigurationFile.cs

And here are the debug configuration class I am using to test the ConfigurationFile class for reference.
https://gitlab.com/XerShade/Esmiylara.Online/blob/alpha-2-dev/source.debug/Esmiylara.Debug/DebugConfig.cs

Any help would be greatly appreciated.

Edit: Here is the generated JSON file just in case anyone needs to see it.

{
"RandomStringValue": "Some profound text will appear here!",
"RandomBooleans": {
"Player 1": false,
"Player 2": false,
"Player 3": false,
"Player 4": false
}
}

Answer

JSON.NET, by default will be unable to determine the object type from the JSON string, so it will deserialize the object type as a JToken.

But you can change the default behavior with the TypeNameHandling setting.

For example:

var dict = new Dictionary<string, object>() 
{
    { "RandomBooleans", new Dictionary<string, bool>() { {"Player 1", true}, {"Player 2", false} }  }
};
var settings = new JsonSerializerSettings()
{
    TypeNameHandling = TypeNameHandling.All
};
var json = JsonConvert.SerializeObject(dict, settings);
var dictDeserialized = JsonConvert.DeserializeObject<Dictionary<string, object>>(json, settings);

Note that you must pass the setting to the serialization and the deserialization calls.

The json generated will look like this:

{  
   "$type":"System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Object, mscorlib]], mscorlib",
   "RandomBooleans":{  
      "$type":"System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Boolean, mscorlib]], mscorlib",
      "Player 1":true,
      "Player 2":false
   }
}