Private setters in Json.Net

I came here looking for the actual attribute that makes Json.NET populate a readonly property when deserializing, and that's simply [JsonProperty], e.g.:

[JsonProperty]
public Guid? ClientId { get; private set; }

Alternative Solution

Just provide a constructor that has a parameter matching your property:

public class Foo
{
    public string Bar { get; }

    public Foo(string bar)
    {
        Bar = bar;
    }
}

Now this works:

string json = "{ \"bar\": \"Stack Overflow\" }";

var deserialized = JsonConvert.DeserializeObject<Foo>(json);
Console.WriteLine(deserialized.Bar); // Stack Overflow

I prefer this approach where possible since:

  • It doesn't require you to decorate your properties with attributes.
  • It works with both { get; private set; } and just { get; }.

Updated, new answer

I've written a source distribution NuGet for this, that installs a single file with two custom contract resolvers:

  • PrivateSetterContractResolver
  • PrivateSetterCamelCasePropertyNamesContractResolver

Install the NuGet package:

Install-Package JsonNet.ContractResolvers

Then just use any of the resolvers:

var settings = new JsonSerializerSettings
{
    ContractResolver = new PrivateSetterContractResolver()
};

var model = JsonConvert.DeserializeObject<Model>(json, settings);

You can read about it here: http://danielwertheim.se/json-net-private-setters-nuget/

GitHub repo: https://github.com/danielwertheim/jsonnet-privatesetterscontractresolvers

Old answer (still valid)

There are two alternatives that can solve the problem.

Alt 1: On the deserializers

ContractResolver.DefaultMembersSearchFlags =
                             DefaultMembersSearchFlags | BindingFlags.NonPublic;

The default serialization option supports all types of class member. Therefore this solution will return all private members types including fields. I'm only interested in also supporting private setters.

Alt2: Create a custom ContractResolver:

Therefore this is the better options since we just check the properties.

public class SisoJsonDefaultContractResolver : DefaultContractResolver 
{
    protected override JsonProperty CreateProperty(
        MemberInfo member,
        MemberSerialization memberSerialization)
    {
        //TODO: Maybe cache
        var prop = base.CreateProperty(member, memberSerialization);

        if (!prop.Writable)
        {
            var property = member as PropertyInfo;
            if (property != null)
            {
                var hasPrivateSetter = property.GetSetMethod(true) != null;
                prop.Writable = hasPrivateSetter;
            }
        }

        return prop;
    }
}

For more information, read my post: http://danielwertheim.se/json-net-private-setters/