简体   繁体   中英

JSON.NET: How deserialize specific Exception type

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}");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM