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

Zok*_*oka 4 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}");
Run Code Online (Sandbox Code Playgroud)

瞧……内部异常类型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;
}
Run Code Online (Sandbox Code Playgroud)

并在调用DeserializeObject上面的函数时传递这个转换器。这一次,我得到了例外:

Newtonsoft.Json.JsonSerializationException:无法将 JSON 对象填充到类型“System.Exception”上。路径“类名”

至于我挖成Newtonsoft.Json代码,它似乎是“问题”是,Exception[Serializable],并ISerializable因此它使用SerializableContract不支持填充对象。但在这里我以绝望结束:-(。有人可以帮助我吗?

(上面的例子只是为了简单起见,我需要序列化和反序列化我自己的异常,这要复杂得多。使用的是 Newtonsoft.Json 版本 11.0.0.2。)

Has*_*ngü 5

你忘记了 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}");
Run Code Online (Sandbox Code Playgroud)