Json.NET可以在类中填充只读字段吗?

时间:2010-11-14 19:01:47

标签: .net json.net

我没有看到很多关于Json.NET支持使用readonly字段反序列化对象的信息。我注意到.NET DataContract和DataMember属性允许在反序列化期间填充readonly字段,但Json.NET似乎不支持这一点,至少从我看到的行为来看。

3 个答案:

答案 0 :(得分:9)

不是最优雅的解决方案,但您可以扩展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。

答案 1 :(得分:2)

现在可以这样做了。使用JsonProperty属性声明属性,并确保它们具有声明的受保护集:

[JsonProperty("Name")] public string Name {get; protected set;}

仅使用get时,这对我不起作用,但与protected set完美配合。

答案 2 :(得分:-2)

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);
    }
}
相关问题