I've been having trouble deserializing custom exceptions in Newtonsoft.Json version 11.0.2. It works fine in Newtonsoft.Json version 10.0.3.
I serialize and deserialize using -
result = JsonConvert.SerializeObject( <<object of type MyHttpException>> );
MyHttpException deserializedException = JsonConvert.DeserializeObject<MyHttpException>(result);
The error I get during deserialization is a Newtonsoft.Json.JsonSerializationException
:
Unable to find a constructor to use for type MyHttpException.
A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.
Path 'HttpStatusCode', line 2, position 19.
If I add a parameterless constructor to MyHttpException and MyBaseException, I don't get any exception. But the InnerException is not deserialized and is null.
Is there something obvious I'm missing? I'm not sure why this would work in 10.0.3 and break in 11.0.2.
My exception classes –
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);
}
}
Thanks
See Question&Answers more detail:
os