JSON.NET: как десериализовать определенный тип исключения - PullRequest
0 голосов
/ 06 сентября 2018

Рассмотрим следующий очень простой код.

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.)

1 Ответ

0 голосов
/ 06 сентября 2018

Вы забыли настройку TypeNameHandling. [ Обработка текста ] Поэтому, пожалуйста, исправьте ваш код следующим образом, он будет работать правильно

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