Working with private setters in Json.NET

How to use a custom contract resolver to deserialize to an object with private setters in Json.NET


A colleague recently came to me asking for help. They had a class that they needed to deserialize from a JSON payload, but all of the setters on the class were private, and the class was owned by a separate team, so they couldn't make any changes to it (such as adding [JsonProperty] attributes, or making the setters public). They wanted to use Json.NET for all of their serialization/deserialization.

Luckily, Json.NET is a very flexible library, so I was able to help them build a custom contract resolver that would make use of the private setters:

class PrivateSetterContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var jsonProperty = base.CreateProperty(member, memberSerialization);
        if (!jsonProperty.Writable)
        {
            if (member is PropertyInfo propertyInfo)
            {
                jsonProperty.Writable = propertyInfo.GetSetMethod(true) != null;
            }
        }

        return jsonProperty;
    }
}

They were quite happy with this solution, as it was very simple, and it didn't require any modification to the class in question.

Here is an example of it in use:

class ExampleClass
{
    public string Key { get; private set; }
}

void Main()
{
    var jsonSerializerSettings = new JsonSerializerSettings()
    {
        ContractResolver = new PrivateSetterContractResolver()
    };

    var json = "{'Key':'Value'}";

    var instance = JsonConvert.DeserializeObject<ExampleClass>(json, jsonSerializerSettings);
    
    // instance.Key == "Value"
}

Hopefully this helps you if you ever run in to a similar issue!


Posted by Matthew King on 11 April 2019
Permission is granted to use all code snippets under CC BY-SA 3.0 (just like StackOverflow), or the MIT license - your choice!