I know there's an attribute to handle private setters but I kind of want this behavior as a default, is there a way to accomplish this? Except tweaking the source. Would be great if there was a setting for this.
-
1I was looking for [this](https://stackoverflow.com/a/32010248/2122718) or [that](https://stackoverflow.com/a/39380844/2122718) answer. – marbel82 Sep 04 '17 at 09:16
5 Answers
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; }
.

- 23,054
- 9
- 78
- 76
-
27Just a tiny note: it works with `{get;private set;}`, not with `{get;}` – tymtam Aug 29 '17 at 01:40
-
12
-
1@Hav What version is it since? I've just tested v11.0.2 and it does **not** work {get;} – tymtam Sep 06 '18 at 01:16
-
1@tymtam I think it only works with `{ get; }` if the type has a constructor with a parameter matching the property name. – Saeb Amini Sep 06 '18 at 03:27
-
-
1@tymtam I haven't been able to find anything in the official doco going to this level of detail. But looking at the code, the deserialization works by first instantiating the object using a nondefault constructor (if any), matching constructor parameter names to property names. It then makes another pass setting properties it couldn't in the constructor. So for a property with `{ get; }`, its only chance would be to use the constructor therefore you need to provide one with a matching parameter name. Have a look at [this answer](https://stackoverflow.com/a/33182520/68080) for some more detail. – Saeb Amini Sep 06 '18 at 03:51
-
2
-
Note that the property name `Bar` must match the constructor parameter name `bar` case insensitive. – huang Nov 06 '19 at 14:46
-
This is right solution it work with {get; private set;} tested in .net 5 – Yogesh Apr 18 '21 at 05:47
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/

- 30,049
- 14
- 78
- 114

- 8,133
- 5
- 36
- 51
-
2Linking to your post http://daniel.wertheim.se/2010/11/06/json-net-private-setters/ – Jafin Apr 21 '11 at 02:15
-
1@Jafin url is dead, https://danielwertheim.wordpress.com/2010/11/06/json-net-private-setters/ has it now – Chris Marisic Jan 05 '15 at 17:28
-
1Looks like **Alt 2** is definitely the way to go nowadays. `DefaultMembersSearchFlags` has been [deprecated](http://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_DefaultContractResolver_DefaultMembersSearchFlags.htm). – Todd Menier Jun 29 '15 at 18:45
-
5With c# 6, `{get; }` is NOT equivalent to `{ get; private set; }`. For the first way `property.GetSetMethod(true)` returns `null` and the latter `true`. This surprised me. You must have `private set;` for deserialization to work as expected. – emragins May 07 '16 at 04:00
-
1It looks like Install-Package JsonNet.ContractResolvers should be used now. https://github.com/danielwertheim/jsonnet-contractresolvers – AlignedDev Dec 03 '19 at 20:49
@Daniel's answer (Alt2) is spot on, but I needed this to work for both private setters and getters (I'm working with an API that actually has a few write-only things, like user.password
.) Here's what I ended up with:
public class NonPublicPropertiesResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) {
var prop = base.CreateProperty(member, memberSerialization);
if (member is PropertyInfo pi) {
prop.Readable = (pi.GetMethod != null);
prop.Writable = (pi.SetMethod != null);
}
return prop;
}
}
Registered thusly:
JsonConvert.DefaultSettings = () => new JsonSerializerSettings {
ContractResolver = new NonPublicPropertiesResolver()
};

- 37,557
- 17
- 150
- 173
Starting from C# 9 it's recommended to use Init Only Setters rather than private setters when initialising an object from JSON. E.g. public string Summary { get; init; }
If you insist on private setters, then you'd need to annotate such properties with JsonInclude attribute.
Either way, JsonSerializer.DeserializeAsync will deserialise the properties.

- 8,168
- 8
- 71
- 87
What the docs have to say about it as per the moment of writing this post:
By default Json.NET will first look for a constructor marked with the JsonConstructorAttribute, then look for a public default constructor (a constructor that doesn't take any arguments), then check if the class has a single public constructor with arguments and finally check for a non-public default constructor.
Goes to say that if you have default constructor (with no arguments) then that will be selected over any other constructors. This can be solved by decorating the desired constructor with JsonConstructorAttribute
.
On a separate note - decorating properties with JsonProperty
does not work for me both with and without constructor.

- 715
- 1
- 8
- 29