Search code examples
c#.netjsonjson.netjsonserializer

How can I "un-JsonIgnore" an attribute in a derived class?


I am using Newtonsoft's JsonSerializer to serialise some classes.

As I wanted to omit one field of my class in the serialisation process, I declared it as follow:

[JsonIgnore]
public int ParentId { get; set; }

This worked, but I am now facing a new problem : In a derived class, I would like this field to appear (and do so only in this specific derived class).

I have been looking through the documentation and on the Internet for a way to override this setting in child classes (I guess I need something like [JsonStopIgnore], but I couldn't find anything close).


  • Is there any way for me to force JsonSerializer to pick up again this attribute ?
  • Is it possible to explicitly mark an attribute as [JsonIgnore], but only in base class ?

Solution

  • You can do this by creating a custom DefaultContractResolver and overriding its CreateProperty method.

    For example, given a Foo base and a derived Bar:

    public class Foo
    {
        [JsonIgnore]
        public string Name { get; set; }
        public int Age { get; set; }
    }
    
    public class Bar : Foo 
    { }
    

    You can create the following contract resolver:

    public class MyTypeContractResolver<T> : DefaultContractResolver
    {
        protected override JsonProperty CreateProperty(MemberInfo member,
                                                       MemberSerialization
                                                           memberSerialization)
        {
            var property = base.CreateProperty(member, memberSerialization);
    
            property.Ignored = false;
            property.ShouldSerialize = propInstance => property.DeclaringType != typeof (T);
            return property;
        }
    }
    

    This will set all properties to Ignored = false, and then analyze them by the given predicate:

    propInstance => property.DeclaringType != typeof (T);
    

    Which in our case means "you should serialize only if they are not of type Foo" (since Foo is the DeclaryingType).

    And then when you want to deserialize, you pass an instance of the contract resolver to JsonSerializerSettings:

    var bar = new Bar();
    var result = JsonConvert.SerializeObject(bar,
        new JsonSerializerSettings {ContractResolver = new MyTypeContractResolver<Bar>()});