【发布时间】:2010-11-14 19:01:46
【问题描述】:
我没有看到太多关于 Json.NET 支持使用 readonly 字段反序列化对象的信息。我确实注意到 .NET DataContract 和 DataMember 属性允许在反序列化期间填充 readonly 字段,但 Json.NET 似乎不支持这一点,至少从我看到的行为来看。
【问题讨论】:
我没有看到太多关于 Json.NET 支持使用 readonly 字段反序列化对象的信息。我确实注意到 .NET DataContract 和 DataMember 属性允许在反序列化期间填充 readonly 字段,但 Json.NET 似乎不支持这一点,至少从我看到的行为来看。
【问题讨论】:
不是最优雅的解决方案,但您可以扩展 DefaultConstractResolver 来做到这一点:
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;
}
}
}
我刚刚从 CanSetMemberValue 方法中删除了一个小检查。不幸的是,它既不是虚拟方法也不是实例方法,所以我也不得不重写 CreateProperty。
【讨论】:
现在可以完成了。使用 JsonProperty 属性声明您的属性,并确保它们声明了受保护的集:
[JsonProperty("Name")] public string Name {get; protected set;}
仅使用 get 时,这对我不起作用,但与 protected set 完美搭配。
【讨论】:
[JsonProperty] 属性
afai 可以看到将字段更改为 readonly 会在反序列化后产生 null 值。我有另一个问题的工作示例(修改如下所示),这就是我看到的行为。
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);
}
}
【讨论】: