I noticed that, by default, JSON.NET will only (de-)serialize an object's public properties. This is good. However, when a property is tagged with a [JsonPropertyAttribute]
, JSON.NET will also access private getters and setters. This is bad.
What I'd like to do to fix this problem is mark the private getter/setter with a [JsonIgnoreAttribute]
.
For example:
public class JsonObject
{
[JsonProperty(PropertyName = "read_write_property")]
public object ReadOnlyProperty
{
get;
[JsonIgnore] private set;
}
}
Unfortunately, that's not valid C# code. So what code would achieve the same result?
Some of the ideas that I know would work:
- Remove the [JsonPropertyAttribute]
- Remove the setter entirely and introduce a backing field
Are these the only two options?
Edit
I added the backing field for my read-only property. Not sure, but I think I found a bug in Json.Net. The serializer will treat the property as non-existent when only a getter exists, even though the specified name attribute matches the JSON string. This is especially annoying, because I'm also using the [JsonExtensionData]
mechanism. So the deserialized value ends up going into my extension data dictionary. Here is the code that demonstrates the problem:
Offending class
using System.ComponentModel;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public class JsonObject
{
private readonly BindingDirection bindingDirection;
public JsonObject()
{
this.bindingDirection = BindingDirection.OneWay;
}
[JsonProperty(PropertyName = "binding_type"), JsonConverter(typeof(StringEnumConverter))]
public BindingDirection BindingDirection
{
get
{
return this.bindingDirection;
}
}
[JsonExtensionData]
public IDictionary<string, object> ExtensionData { get; set; }
}
Demonstration
using Newtonsoft.Json;
class Program
{
static void Main(string[] args)
{
var obj = new JsonObject();
var serialized = JsonConvert.SerializeObject(obj);
var deserialized = JsonConvert.DeserializeObject<JsonObject>(serialized);
Console.WriteLine("*** Extension data ***\n");
foreach (var kvp in deserialized.ExtensionData)
{
Console.WriteLine("{0} == {1}", kvp.Key, kvp.Value);
}
Console.ReadLine();
}
}
Output
*** Extension data ***
binding_type == OneWay