我在Newtonsoft.Json版本11.0.2中反序列化自定义异常时遇到了问题 . 它在Newtonsoft.Json版本10.0.3中工作正常 .
我使用 - 序列化和反序列化 -
result = JsonConvert.SerializeObject( <<object of type MyHttpException>> );
MyHttpException deserializedException = JsonConvert.DeserializeObject<MyHttpException>(result);
我在反序列化期间得到的错误是 Newtonsoft.Json.JsonSerializationException
:
无法找到用于MyHttpException类型的构造函数 . 一个类应该有一个默认的构造函数,一个带参数的构造函数或一个用JsonConstructor属性标记的构造函数 . Path'HttpStatusCode',第2行,第19位 .
如果我向MyHttpException和MyBaseException添加无参数构造函数,我不会得到任何异常 . 但是InnerException没有反序列化并且为null .
有什么明显的东西我不见了吗?我不确定为什么这会在10.0.3中起作用并在11.0.2中中断 .
我的例外类 -
public sealed class MyHttpException : MyBaseException
{
public MyHttpException(HttpStatusCode httpStatusCode, int MyStatusCode)
: base(MyStatusCode) => HttpStatusCode = httpStatusCode;
public MyHttpException(HttpStatusCode httpStatusCode, int MyStatusCode, string message)
: base(MyStatusCode, message) => HttpStatusCode = httpStatusCode;
public MyHttpException(HttpStatusCode httpStatusCode, int MyStatusCode, Exception innerException)
: base(MyStatusCode, innerException) => HttpStatusCode = httpStatusCode;
public MyHttpException(HttpStatusCode httpStatusCode, int MyStatusCode, string message, Exception innerException)
: base(MyStatusCode, message, innerException) => HttpStatusCode = httpStatusCode;
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
private MyHttpException(SerializationInfo info, StreamingContext context)
: base(info, context) => HttpStatusCode = (HttpStatusCode)info.GetValue("HttpStatusCode", typeof(HttpStatusCode));
public HttpStatusCode HttpStatusCode { get; set; }
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
{
throw new ArgumentNullException("info");
}
info.AddValue("HttpStatusCode", HttpStatusCode);
// MUST call through to the base class to let it save its own state
base.GetObjectData(info, context);
}
}
public abstract class MyBaseException : Exception
{
public MyBaseException(int MyStatusCode) => this.MyStatusCode = MyStatusCode;
public MyBaseException(int MyStatusCode, string message)
: base(message) => this.MyStatusCode = MyStatusCode;
public MyBaseException(int MyStatusCode, Exception innerException)
: base("MyErrorCode: " + MyStatusCode + ". " + MyStatusCodes.GetDescription(MyStatusCode) + ". " + innerException.Message, innerException) => this.MyStatusCode = MyStatusCode;
public MyBaseException(int MyStatusCode, string message, Exception innerException)
: base(message, innerException) => this.MyStatusCode = MyStatusCode;
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
protected MyBaseException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
MyStatusCode = info.GetInt32("MyStatusCode");
}
public int MyStatusCode { get; set; }
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
{
throw new ArgumentNullException("info");
}
info.AddValue("MyStatusCode", MyStatusCode);
// MUST call through to the base class to let it save its own state
base.GetObjectData(info, context);
}
}
谢谢
1 回答
在Json.NET 11中,对如何序列化
ISerializable
类型进行了更改 . 根据release notes:因此,您现在必须使用SerializableAttribute标记您的异常类型:
或者,您可以创建一个恢复旧行为的custom contract resolver:
(你可能想cache the contract resolver for best performance . )
为什么要做出这种改变?根据Issue #1622: classes deriving from System.Exception do not serialize/deserialize properly:
反过来,链接的问题dotnet/corefx Issue #23415: PlatformNotSupportedException when attempting to serialize DirectoryInfo instance with Newtonsoft.Json表示更改是在.NET Core团队的请求下进行的:
因此,如果您使用
PreferISerializableContractResolver
而不是使用[Serializable]
标记ISerializable
类型,则可能会在.NET Core中遇到此问题 .