JSON.NET:如何反序列化特定的异常类型

时间:2018-09-06 08:35:42

标签: c# json.net json-deserialization

考虑以下非常简单的代码。

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 :(得分:3)

您忘记了TypeNameHandling设置。[Typehandling] 因此,请按照以下步骤修复您的代码,它将正常运行

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