Рассмотрим следующий очень простой код.
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}");
И вуаля ... тип внутреннего исключения Exception
вместо NullReferenceException
.
Поэтому я искал SO и нашел много примеров с пользовательским JsonConverter
, используемым для десериализации (поскольку сериализованный JSON содержит свойство ClassName
, которое можно использовать для создания определенного типа). Поэтому я написал один (только ReadJson
присутствует для простоты, отдых как обычно).
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;
}
И передать этот преобразователь при вызове функции DeserializeObject
выше.
На этот раз я получаю исключение:
Newtonsoft.Json.JsonSerializationException: Cannot populate JSON object onto type 'System.Exception'. Path 'ClassName'
Насколько я копался в коде Newtonsoft.Json, похоже, "проблема" в том, что Exception
равен [Serializable]
и ISerializable
, поэтому он использует SerializableContract, который не поддерживает заполнение объекта. Но здесь я заканчиваю в отчаянии :-(. Может ли кто-нибудь мне помочь?
(Пример выше для простоты, мне нужно сериализовать и десериализовать мои собственные исключения, которые гораздо сложнее. Используется Newtonsoft.Json версии 11.0.0.2.)