.NET 异常序列化在没有遗留模式的情况下不再工作,Newtonsoft.Json - 故意的?

问题描述 投票:0回答:1

这个问题指的是仍然使用Newtonsoft.Json的代码。以下测试也使用了 System.Text.Json。

我最终想从我的例外中删除过时的模式,包括

[SerializableAttribute]
、受保护的 ctor 和
GetObjectData(SerializationInfo, StreamingContext)

现在序列化器,

System.Text.Json.JsonSerializer
Newtonsoft.Json.JsonConvert
都不能正确反序列化异常:

虽然不依赖于旧的

IFormatter
(真的不是吗?),[编辑] Newtonsoft.Json 序列化和反序列化异常实现了旧模式。现在,反序列化甚至不会重现原始异常消息,而是在反序列化时创建一条新消息
SomeIdNotFoundException
:

抛出了“...SomeIdNotFoundException”类型的异常。

我发现异常类,包括自定义和常见的 .NET 类型,包括基本的

System.Exception
,通过拥有私有/受保护和只读成员,不符合(反)序列化的通常要求,但这是故意的吗丢失所有异常内容,除非使用特殊配置?

编辑:示例

使用遗留序列化

using System;
using System.Runtime.Serialization;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[Serializable]
public class SomeIdNotFoundException : Exception
{
    public SomeIdNotFoundException()
    { }

    public SomeIdNotFoundException(string message)
        : base(message)
    { }

    public SomeIdNotFoundException(string message, Exception innerException)
        : base(message, innerException)
    { }

    protected SomeIdNotFoundException(SerializationInfo info, StreamingContext context)
        : base(info, context)
    { }

    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        base.GetObjectData(info, context);
    }
}

[TestClass]
public class ExceptionSerializationTests
{
    [TestMethod]
    public void SomeIdNotFoundException_Serialization_RoundTrip()
    {
        var expectedMessage = "Some ID not found.";
        var originalException = new SomeIdNotFoundException(expectedMessage);
        //var originalException = Assert.ThrowsException<SomeIdNotFoundException>(
        //    () => throw new SomeIdNotFoundException(expectedMessage));

        var deserializedException = SerializeAndDeserialize(originalException);

        Assert.AreEqual(expectedMessage, deserializedException.Message);
    }

    private static SomeIdNotFoundException SerializeAndDeserialize(SomeIdNotFoundException exceptionToSerialize)
    {
        //var serializedException = System.Text.Json.JsonSerializer.Serialize(exceptionToSerialize);
        //return System.Text.Json.JsonSerializer.Deserialize<SomeIdNotFoundException>(serializedException)!;
        var serializedException = Newtonsoft.Json.JsonConvert.SerializeObject(exceptionToSerialize);
        return Newtonsoft.Json.JsonConvert.DeserializeObject<SomeIdNotFoundException>(serializedException)!;
    }

    public static void Main(string[] args)
    {
        new ExceptionSerializationTests()
            .SomeIdNotFoundException_Serialization_RoundTrip();
    }
}

没有遗留序列化

仅限异常类。

// no Serializable attribute
public class SomeIdNotFoundException : Exception
{
    public SomeIdNotFoundException()
    { }

    public SomeIdNotFoundException(string message)
        : base(message)
    { }

    public SomeIdNotFoundException(string message, Exception innerException)
        : base(message, innerException)
    { }
}

直接异常实例化(不抛出)

禁用旧模式

使用 SystemNewtonsoft 进行反序列化,序列化程序会生成此类新的异常消息:

抛出了“[namespace].SomeIdNotFoundException”类型的异常。

遗留模式仍然可用

  • System.Text.Json 的行为类似于没有遗留模式,使用新的异常消息创建反序列化异常。
  • Newtonsoft.Json 执行该方法的完整反序列化,保留原始消息。

抛出异常

抛出异常,就像用

Assert.ThrowsException<SomeIdNotFoundException>(...)
注释掉的部分一样。然后,反序列化永远不会与 System.Text.Json 一起工作,无论是否实现了遗留模式。

System.Text.Json抛出的异常的错误消息:

System.NotSupportedException:不支持“System.Reflection.MethodBase”实例的序列化和反序列化。路径:$.TargetSite。 ---> System.NotSupportedException:不支持“System.Reflection.MethodBase”实例的序列化和反序列化。

Newtonsoft.Json

只要遗留模式可用,就没有抛出异常的问题。

c# .net exception serialization deserialization
1个回答
0
投票

    Newtonsoft.Json
  • 支持异常的旧序列化模式。
  • System.Text.Json
  • 默认情况下从不支持异常序列化。
  • 如果没有遗留模式或特定编码,这些 JSON 序列化都不支持异常序列化。

另请参阅问题下评论中来自 @dbc 的链接!

© www.soinside.com 2019 - 2024. All rights reserved.