Search code examples
c#jsonjson.netpolymorphism

Prevent JSON.net to serialize derived type properties when declared as a base type


Given:

class Mammal
{
    public int Age { get; set; }
}

class Human : Mammal
{
    public string Name { get; set; }
}

class Stuff
{
    public Mammal Mammal { get; set; }
}

And

var stuff = new Stuff
{
    Mammal = new Human
    {
        Name = "test",
        Age = 12
    }
};

Console.WriteLine(JsonConvert.SerializeObject(stuff));

I get:

{"Mammal":{"Name":"test","Age":12}}

But I only want to get properties defined in type statically (meaning that I shouldn't see the name in the JSON), not runtime-type properties. How to do that?


Solution

  • You can try extending DefaultContractResolver:

    public class MyContractResolver : DefaultContractResolver
    {
        protected override JsonContract CreateContract(Type objectType)
        {
            // Of course, the logic here is up to you!
            if (objectType == typeof(Human))
            {
                return base.CreateContract(typeof(Mammal)); 
            }
            return base.CreateContract(objectType);
        }
    }
    

    It simply says - if the object serialized is of type Human, serialize it accordingly to the contract of the base class Mammal. Which is exactly what you want. This then should be used like this:

    var stuff = new Stuff
    {
        Mammal = new Human
        {
            Name = "test",
            Age = 12
        }
    };
    
    var json = JsonConvert.SerializeObject(
        stuff,
        Formatting.Indented,
        new JsonSerializerSettings 
        { 
            ContractResolver = new MyContractResolver() 
        });
    

    Reference: Contract Resolvers