17

I want to JSON serialize a custom exception object which inherits System.Exception. JsonConvert.SerializeObject seems to ignore properties from the derived type. The problem can be illustrated very simply:

class MyException : Exception {
    public string MyProperty { get; set; }
}

class Program {
    static void Main(string[] args) {
        Console.WriteLine(JsonConvert.SerializeObject(new MyException {MyProperty = "foobar"}, Formatting.Indented));
        //MyProperty is absent from the output. Why?
        Console.ReadLine();
    }
}

I've tried adding the DataContract and DataMember attributes in the correct places. They don't help. How do I get this to work?

2
  • 1
    Exception is ISerializable. Try to override that. Commented Nov 28, 2014 at 23:50
  • I found the same solution as Thomas. Extending the ISerializable implementation is better than ignoring it. Consider, ISerializable was implemented by the creator of the base class for a reason. Ignoring it bypasses all of their work. When I used IgnoreSerializableInterface with my exception, the ClassName property was not included. As a result, I was unable to de-serialize it later. Extending GetObjectData and the constructor works perfectly. (I would have left this as a comment, but I have no reputation yet.) Commented Feb 8, 2017 at 15:58

2 Answers 2

19

Because Exception implements ISerializable, Json.Net uses that to serialize the object by default. You can tell it to ignore ISerializable like so:

var settings = new JsonSerializerSettings() {
    Formatting = Formatting.Indented,
    ContractResolver = new DefaultContractResolver() { 
        IgnoreSerializableInterface = true 
    } 
};
Console.WriteLine(JsonConvert.SerializeObject(new MyException {MyProperty = "foobar"}, settings));
Sign up to request clarification or add additional context in comments.

3 Comments

This will cause errors because exceptions have self-referencing members. You have to specify ReferenceLoopHandling = ReferenceLoopHandling.Ignore in the JsonSerializerSettings in addition to your code. Anyway I think serializing an exception this way is a really bad idea as the TargetSite property can generate a REALLY heavy string (like several MBytes).
@MaximeRossini, you are right. But it's possible to use DynamicContractResolver for ignoring TargetSite property.
@MaximeRossini FYI, TargetSite is no longer included when serializing as per this PR
8

You could also add and retrieve a specific object into the System.Runtime.Serialization.SerializationInfo store by overriding the GetObjectData method and the ctor(SerializationInfo, StreamingContext):

public class MyCustomException : Exception
{
    public string MyCustomData { get; set; }

    protected MyCustomException (SerializationInfo info, StreamingContext context) : base(info, context)
    {
        MyCustomData = info.GetString("MyCustomData");
    }

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

This way the MyCustomObject property will get included in serialization and deserialization.

1 Comment

In addition to this, I needed to add the [Serializable] attribute to the derived exception class for it to work

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.