Newtonsoft Json.NET do not serialize [Obsolete] property

Viewed 1217

Is there a way to configure Json.NET to not serialize properties which have an [Obsolete] attribute?

e.g.

public class Foo
{
    public int Id { get; set; }

    [Obsolete]
    public int Age { get; set; }
 }

 var foo = new Foo { Id = 123, Age = 23 };
 var json = JsonConvert.SerializeObject(foo);

In the above example, the json is {"Id":123,"Age":23}

I would like {"Id":123}

3 Answers

Yes, you can use a custom ContractResolver to exclude properties marked obsolete.
Here is the code you would need for the resolver:

public class ExcludeObsoletePropertiesResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty prop = base.CreateProperty(member, memberSerialization);
        if (prop.AttributeProvider.GetAttributes(true).OfType<ObsoleteAttribute>().Any())
        {
            prop.ShouldSerialize = obj => false;
        }
        return prop;
    }
}

Then use it like this:

var settings = new JsonSerializerSettings
{
    ContractResolver = new ExcludeObsoletePropertiesResolver()
};
var json = JsonConvert.SerializeObject(foo, settings);

Working demo here: https://dotnetfiddle.net/gIRCD4

You can utilise conditional serialisation as documented here: https://www.newtonsoft.com/json/help/html/ConditionalProperties.htm

If you have control over the class and want to target specific properties you know upfront it would be easier to use the first mechanism, offering ShouldSerializeAge() method

But most probably it seems you need something generic in this case you can create a IContractResolver class that uses Reflection to check whether a given property has the Obselete attribute

Expanding on Brian Rogers' answer: It's a little bit simpler/faster to filter out the members to exclude in an override of GetSerializableMembers() method rather than the CreateProperty(MemberInfo member, MemberSerialization memberSerialization) which gets called for on each MemberInfo returned by GetSerializedMembers() to avoid unnecessary calls to the CreateProperty method which does a bunch of reflection and delegate creation.

public class ExcludeObsoletePropertiesResolver : DefaultContractResolver
{
    protected override List<MemberInfo> GetSerializableMembers(Type objectType)
    {
        var members =  base.GetSerializableMembers(objectType);
        members.RemoveAll(m => m.IsDefined(typeof(ObsoleteAttribute), true));
        return members;
    }
}

Usage:

var settings = new JsonSerializerSettings
{
    ContractResolver = new ExcludeObsoletePropertiesResolver()
};
var json = JsonConvert.SerializeObject(foo, settings);
Related