Rex M Rex M - 1 month ago 23
C# Question

Exclude property from serialization via custom attribute (json.net)

I need to be able to control how/whether certain properties on a class are serialized. The simplest case is

[ScriptIgnore]
. However, I only want these attributes to be honored for this one specific serialization situation I am working on - if other modules downstream in the application also want to serialize these objects, none of these attributes should get in the way.

So my thought is to use a custom attribute
MyAttribute
on the properties, and initialize the specific instance of JsonSerializer with a hook that knows to look for that attribute.

At first glance, I don't see any of the available hook points in JSON.NET will provide the
PropertyInfo
for the current property to do such an inspection - only the property's value. Am I missing something? Or a better way to approach this?

Answer

You have a few options. I recommend you read the Json.Net documentation article on the subject before reading below.

The article presents two methods:

  1. Create a method that returns a bool value based on a naming convention that Json.Net will follow to determine whether or not to serialize the property.
  2. Create a custom contract resolver that ignores the property.

Of the two, I favor the latter. Skip attributes altogether -- only use them to ignore properties across all forms of serialization. Instead, create a custom contract resolver that ignores the property in question, and only use the contract resolver when you want to ignore the property, leaving other users of the class free to serialize the property or not at their own whim.

Edit To avoid link rot, I'm posting the code in question from the article

public class ShouldSerializeContractResolver : DefaultContractResolver
{
   public new static readonly ShouldSerializeContractResolver Instance =
                                 new ShouldSerializeContractResolver();

   protected override JsonProperty CreateProperty( MemberInfo member,
                                    MemberSerialization memberSerialization )
   {
      JsonProperty property = base.CreateProperty( member, memberSerialization );

      if( property.DeclaringType == typeof(Employee) &&
            property.PropertyName == "Manager" )
      {
         property.ShouldSerialize = instance =>
         {
            // replace this logic with your own, probably just  
            // return false;
            Employee e = (Employee)instance;
            return e.Manager != e;
         };
      }

      return property;
   }
}