Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON.NET is ignoring properties in types derived from System.Exception. Why?

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?

like image 482
wwarby Avatar asked Nov 28 '14 23:11

wwarby


People also ask

Which of the following attributes are required to ignore properties for Json serializer?

To ignore individual properties, use the [JsonIgnore] attribute.

Can I optionally turn off the JsonIgnore attribute at runtime?

Yes, add prop. PropertyName = prop. UnderlyingName; inside the loop in the resolver. This will cause the property to use its original name.

Which of the following attribute should be used to indicate the property must not be serialized while using .Json serializer?

We still use [JsonIgnore] attribute, adding it to the property which we do not want to be serialized.

What is ReferenceLoopHandling?

ReferenceLoopHandling Property. Gets or sets how reference loops (e.g. a class referencing itself) are handled. The default value is Error. Namespace: Newtonsoft.Json. Assembly: Newtonsoft.Json (in Newtonsoft.Json.dll) Version: 12.0.1+509643a8952ce731e0207710c429ad6e67dc43db.


2 Answers

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));
like image 89
Mike Zboray Avatar answered Oct 08 '22 22:10

Mike Zboray


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.

like image 40
Thomas C. G. de Vilhena Avatar answered Oct 08 '22 21:10

Thomas C. G. de Vilhena