I haven\'t seen much information about Json.NET supporting deserializing objects with readonly
fields. I do notice that the .NET DataContract and DataMember att
afai can see changing a field to readonly
results in a null
value after deserialization. I had a working sample for another question (modified as shown below), and that's the behaviour I see.
public class NameAndId
{
public string name;
public int id;
}
public class Data
{
public NameAndId[] data;
}
public class Target
{
public string id;
public readonly NameAndId from;
public DateTime updated_time;
public readonly string message;
public Data likes;
}
public class Program
{
static void Main(string[] args)
{
string json = File.ReadAllText(@"c:\temp\json.txt");
Target newTarget = JsonConvert.DeserializeObject<Target>(json);
}
}
Not the most elegant solution, but you can extend the DefaultConstractResolver to do it:
public class ContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
property.Writable = CanSetMemberValue(member, true);
return property;
}
public static bool CanSetMemberValue(MemberInfo member, bool nonPublic)
{
switch (member.MemberType)
{
case MemberTypes.Field:
var fieldInfo = (FieldInfo)member;
return nonPublic || fieldInfo.IsPublic;
case MemberTypes.Property:
var propertyInfo = (PropertyInfo)member;
if (!propertyInfo.CanWrite)
return false;
if (nonPublic)
return true;
return (propertyInfo.GetSetMethod(nonPublic) != null);
default:
return false;
}
}
}
I have just remove one little check from the CanSetMemberValue method. Unfortunately it's neither virtual nor an instance method, so I had to override CreateProperty as well.
This can be done now. Declare your properties using the JsonProperty
attribute, and ensure that they have a protected set declared:
[JsonProperty("Name")] public string Name {get; protected set;}
This didn't work for me when using only a get
, but works perfectly with the protected set
.