Deserializing ConcurrentDictionary with derived types

May 10, 2011 at 6:34 PM
Edited May 10, 2011 at 6:41 PM

This is a copy of a post on SO (http://stackoverflow.com/questions/5943764/deserializing-dictionary-with-derived-types-using-newtonsofts-json-library).

Given the following class structure, which includes a ConcurrentDictionary of derived objects, how can I serialize and

deserialize using NewtonSoft’s Json library? When I deserialize, I am getting an exception. It looks like it is

having issues reconstituting the dictionary.

[JsonObject(MemberSerialization.OptIn)] 
public class GameObject 
{ 
   
[JsonProperty] 
   
public string Id { get; set; } 
 
   
[JsonProperty] 
   
public string Name { get; set; } 
 
   
[JsonProperty] 
   
public ConcurrentDictionary<string, Component> Components; 
 
   
public GameObject() 
   
{ 
       
Components = new ConcurrentDictionary<string, Component>(); 
   
} 
 
} 
 
[JsonObject(MemberSerialization.OptIn)] 
public class Component 
{ 
   
[JsonIgnore] // Ignore circular reference 
   
public GameObject GameObject { get; set; } 
 
   
public Component() 
   
{ 
   
} 
} 
 
[JsonObject(MemberSerialization.OptIn)] 
public class TestComponent : Component 
{ 
   
[JsonProperty] 
   
public int MyProperty { get; set; } 
 
   
public TestComponent() 
   
{ 
   
} 
} 
 
 
 
 
var originalJson = JsonConvert.SerializeObject(srcObject, Formatting.None,  
   
new JsonSerializerSettings 
               
{ 
                   
TypeNameHandling = TypeNameHandling.All, 
                   
TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple 
               
}); 
 
var newObject = JsonConvert.DeserializeObject<GameObject>(originalJson,  
   
new JsonSerializerSettings() 
               
{ 
                   
TypeNameHandling = TypeNameHandling.All, 
                   
TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple 
               
}); 

Exception on the DeserializeObject call:

System.Reflection.TargetInvocationException was unhandled by user code 
 
Message=Exception has been thrown by the target of an invocation. 
 
Source=mscorlib 
 
StackTrace: 
       at
System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner) 
       at
System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner) 
       at
System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) 
       at
System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 
       at
System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) 
       at
Newtonsoft.Json.Serialization.JsonContract.InvokeOnDeserialized(Object o, StreamingContext context) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonContract.cs:line 135 
       at
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateDictionary(IWrappedDictionary dictionary, JsonReader reader, JsonDictionaryContract contract, String id) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 638 
       at
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateAndPopulateDictionary(JsonReader reader, JsonDictionaryContract contract, String id) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 593 
       at
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 387 
       at
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 223 
       at
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueProperty(JsonReader reader, JsonProperty property, Object target, Boolean gottenCurrentValue, Object currentValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 198 
       at
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, String id) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 876 
       at
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateAndPopulateObject(JsonReader reader, JsonObjectContract contract, String id) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 846 
       at
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 396 
       at
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 223 
       at
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueNonProperty(JsonReader reader, Type objectType, JsonContract contract) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 208 
       at
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 120 
       at
Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonSerializer.cs:line 421 
       at
Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonSerializer.cs:line 413 
       at
Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonConvert.cs:line 721 
       at
Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) in d:\Development\Releases\Json\Working\Src\Newtonsoft.Json\JsonConvert.cs:line 683 
       at MF
.Tests.GameServer.ComponentSerializationTests.TestSerializationOfObjectWithComponent() in C: \ComponentSerializationTests.cs:line 119 
 
InnerException: System.NullReferenceException 
       
Message=Object reference not set to an instance of an object. 
       
Source=mscorlib 
       
StackTrace: 
            at
System.Collections.Concurrent.ConcurrentDictionary`2.InitializeFromCollection(IEnumerable`1 collection) 
            at
System.Collections.Concurrent.ConcurrentDictionary`2.OnDeserialized(StreamingContext context) 
       InnerException: 

Update:

If change the ConcurrentDictionary to a List or a Dictionary, the code works as expected. What am I doing wrong?

What am I doing wrong?

Oct 18, 2011 at 2:43 AM

Having the same problem

Oct 31, 2011 at 5:08 PM

Also having the same issue.

Coordinator
Oct 31, 2011 at 11:52 PM

Fixed.