Consider the following very simple code.
var ex_to_serialize = new Exception("something wrong", new NullReferenceException("set to null"));
var serialized_ex = JsonConvert.SerializeObject(ex_to_serialize);
var deserialized_ex = JsonConvert.DeserializeObject<Exception>(serialized_ex);
Console.WriteLine($"Type of inner exception: {deserialized_ex.InnerException.GetType().Name}");
And voilá... the inner exception type is Exception
instead of NullReferenceException
.
So I searched SO and find lot of example with custom JsonConverter
used for desrialization (as the serialized JSON contains ClassName
property, which could be used to create the specific type). So I wrote one (only ReadJson
is present for simplicity, rest is as usual).
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var json_object = Newtonsoft.Json.Linq.JObject.Load(reader);
var target_type_name = json_object.Value<string>("ClassName");
var target_type = Type.GetType(target_type_name);
var target = Activator.CreateInstance(target_type);
serializer.Populate(json_object.CreateReader(), target);
return target;
}
And pass this converter when calling DeserializeObject
function above.
This time, I get exception:
Newtonsoft.Json.JsonSerializationException: Cannot populate JSON object onto type 'System.Exception'. Path 'ClassName'
As far as I dug into the Newtonsoft.Json code, it seems the "problem" is that Exception
is [Serializable]
and ISerializable
so it uses SerializableContract which does not support populating object. But here I end in desperation :-(. Could someone help me?
(The example above is just for simplicity, I need to serialize and deserialize my own exceptions, which are far more complex. Newtonsoft.Json version 11.0.0.2 used.)
You are forgetting TypeNameHandling setting.[Typehandling] So please fix your code like the following, it will work properly
var ex_to_serialize = new Exception("something wrong", new NullReferenceException("set to null"));
var serialized_ex = JsonConvert.SerializeObject(ex_to_serialize,new JsonSerializerSettings{TypeNameHandling = TypeNameHandling.All});
var deserialized_ex = JsonConvert.DeserializeObject<Exception>(serialized_ex, new JsonSerializerSettings{TypeNameHandling = TypeNameHandling.All});
Console.WriteLine($"Type of inner exception: {deserialized_ex.InnerException.GetType().Name}");