Advanced Newtonsoft.Json: Dynamically rename or ignore properties without changing the serialized class

November 2, 2017, 6 comments, Software Development

This article describes how to implement a custom contract resolver, so that you can ignore or rename serialized JSON properties where the serialization happens and without changing the serialized classes. I use this resolver in my project NSwag, a Swagger/Open API toolchain: A Swagger specification uses JSON Schemas to describe types, but it is not exactly the same model – some properties of a schema are not allowed and some must be renamed. Because I cannot change the JSON Schema implementation, I had to ignore or rename properties in the Swagger serializer. Another use case of this contract resolver is, if you want to conditionally remove or rename properties – for example you want to serialize a property in a test environment but for security reasons you want to remove it in the production deployment (e.g. the stack trace of an exception).

Let’s have a look at the standard way to ignore or rename a property with Newtonsoft.Json:

public class Person
    // ignore property
    public string Title { get; set; }

    // rename property
    public string FirstName { get; set; }

As you can see, the property Title is always ignored and the property FirstName is always serialized as firstName. Also you need to add attributes to the original Person class. To avoid this inflexible approach, you need a custom resolver which decides at runtime how/if to serialize a property. This will look as following:

var person = new Person();

var jsonResolver = new PropertyRenameAndIgnoreSerializerContractResolver();
jsonResolver.IgnoreProperty(typeof(Person), "Title");
jsonResolver.RenameProperty(typeof(Person), "FirstName", "firstName");

var serializerSettings = new JsonSerializerSettings();
serializerSettings.ContractResolver = jsonResolver;

var json = JsonConvert.SerializeObject(person, serializerSettings);

As you can see, we instantiate a new custom contract resolver PropertyRenameAndIgnoreSerializerContractResolver, register the property ignores and renames and pass the resolver to the serializer.

Finally, let’s have a look at the actual contract resolver implementation:

public class PropertyRenameAndIgnoreSerializerContractResolver : DefaultContractResolver
    private readonly Dictionary<Type, HashSet<string>> _ignores;
    private readonly Dictionary<Type, Dictionary<string, string>> _renames;

    public PropertyRenameAndIgnoreSerializerContractResolver()
        _ignores = new Dictionary<Type, HashSet<string>>();
        _renames = new Dictionary<Type, Dictionary<string, string>>();

    public void IgnoreProperty(Type type, params string[] jsonPropertyNames)
        if (!_ignores.ContainsKey(type))
            _ignores[type] = new HashSet<string>();

        foreach (var prop in jsonPropertyNames)

    public void RenameProperty(Type type, string propertyName, string newJsonPropertyName)
        if (!_renames.ContainsKey(type))
            _renames[type] = new Dictionary<string, string>();

        _renames[type][propertyName] = newJsonPropertyName;

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

        if (IsIgnored(property.DeclaringType, property.PropertyName))
            property.ShouldSerialize = i => false;

        if (IsRenamed(property.DeclaringType, property.PropertyName, out var newJsonPropertyName))
            property.PropertyName = newJsonPropertyName;

        return property;

    private bool IsIgnored(Type type, string jsonPropertyName)
        if (!_ignores.ContainsKey(type))
            return false;

        return _ignores[type].Contains(jsonPropertyName);

    private bool IsRenamed(Type type, string jsonPropertyName, out string newJsonPropertyName)
        Dictionary<string, string> renames;

        if (!_renames.TryGetValue(type, out renames) || !renames.TryGetValue(jsonPropertyName, out newJsonPropertyName))
            newJsonPropertyName = null;
            return false;

        return true;

As you can see, the implementation is very simple: We just save the ignore and rename registrations and modify the property contract in the CreateProperty(...) method if necessary.

The original implementation can be found in this GitHub repositiory.

Tags: , , ,

6 responses to “Advanced Newtonsoft.Json: Dynamically rename or ignore properties without changing the serialized class”

  1. mehmet yalçın says:

    Thanks for the snippet. I have a problem when I use it for nested objects’ property ignore. At the second level, this doesn’t work. Is there any workaround? My example: public class School{ public string Name {get;set;} public State State {get;set;} } public class State{ public string StateName {get;set;} public int StateCode {get;set;} } var jsonResolver = new PropertyRenameAndIgnoreSerializerContractResolver(); jsonResolver.IgnoreProperty(typeof(State), “StateName”); var serializerSettings = new JsonSerializerSettings(); serializerSettings.ContractResolver = jsonResolver; var json = JsonConvert.SerializeObject(school, serializerSettings); //result: All properties are serialized.

    • Rico Suter says:

      The name of the property has to be in the JSON form, not the C# form. So maybe the serializer uses camel case and you need to specify it as “stateName”?

      • mehmet yalçın says:

        In fact, I had used base interface in IgnoreProperty method;

        jsonResolver.IgnoreProperty(typeof(IBaseObject), “Name”);

        But the final object is a class derived IBaseObject generic type.

        I solved the problem in this way;

        var type = finalObject.GetType().BaseType;

        jsonResolver.IgnoreProperty(type , “Name”); …

  2. Henri Merkesdal says:

    Excellent, just what I needed, and works like a charm.
    I wanted to hide some values from my Web.Api, while storing all values in Cosmos DB.

  3. Randy Kreisel says:

    This works great with most classes, but if I try to ignore properties of an Exception, it never goes through the CreateProperty method. It’s like the serializer doesn’t recognize it as a target Type.

    var jsonResolver = new PropertyIgnoreSerializerContractResolver();

    jsonResolver.IgnoreProperty(typeof(Exception), “StackTrace”);

    var serializerSettings = new JsonSerializerSettings
    ContractResolver = jsonResolver

    var actual = JsonConvert.SerializeObject(ex, serializerSettings);

    after execution actual still has the StackTrace content

    if I run an object I created, through the resolver I can see it stop in the CreateProperty method for each field, but with the Exception object it never hits the CreateProperty method.

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    Markdown is turned off in code blocks:
     [This is not a link](

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see

This site uses Akismet to reduce spam. Learn how your comment data is processed.