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

November 2, 2017, (updated on July 27, 2018), 13 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;
            property.Ignored = true;

        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: , , ,

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

  1. Cherie says:


    From everything I’ve looked at, this looks like the closest to what I’m looking for, but it’s still not 100% there. Was hoping you could help.

    This is the background to the problem:
    We are using EF6 database first and we have some very complex entity objects, so we are always running into self referencing problems when serializing entities. We’ve tried things like disabling lazy loading, but still have the problem because if you have three classes, A, B and C, where A references B and B references C, if C has a reference to A it causes a circular reference.
    We cannot annotate the entity classes because the annotations will be deleted when we update from the DB and run the custom tool.

    What I’m trying to achieve:
    I want to create dynamic data contracts so that depending on which api is called, an entity will serialize in a specific way.
    I’m sure I could manipulate your code to do this for a simple entity object, but I want to be able to specify dynamic data contracts for the nested entity objects.

    So for example, again for classes A, B and C where A references B and B references C, I want to be able to say for class A, I want properties 1, 2, 3; For B I want properties 1, 3; For C I want property 5 only.

    A real example is where we have the classes User, Roles and UserRoles.
    User references UserRoles and UserRoles references Roles.
    When I request a list of Users, I want the UserRoles for each user and for each UserRole, I want the Role Description, but not all the Properties in UserRoles or Roles.

    I’m not sure if this is at all possible? If it is should I be using Custom Contract Resolvers or Custom Converters?

    I would really appreciate some assistance.

    • Rico Suter says:

      I think for this scenario you need to implement a custom contract resolver which can be parametrized according to the needs at runtime…

  2. William says:

    Great post! Thanks

  3. Anderson says:

    Another improvement: ignore base class (util in linq serialization):

    private bool IsIgnored(Type type, string jsonPropertyName)
    Type ignoredType = null;

    if (_ignores.ContainsKey(type))
    ignoredType = type;
    if (_ignores.ContainsKey(type.BaseType))
    ignoredType = type.BaseType;

    if (ignoredType == null)
    return false;

    return _ignores[ignoredType].Contains(jsonPropertyName);

  4. Anderson says:

    adding the code below (“property.Ignored = true”) make the “swagger” ignore property showing the schema. Works better to me. Thanks!

    if (IsIgnored(property.DeclaringType, property.PropertyName))
    property.ShouldSerialize = i => false;
    property.Ignored = true; /add this/

  5. Anderson says:

    Works great! Thanks!

  6. 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”); …

  7. 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.

  8. 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.