2010-11-14 21 views
6

我還沒有看到有關Json.NET支持使用readonly字段反序列化對象的很多信息。我注意到.NET DataContract和DataMember屬性允許在反序列化過程中填充readonly字段,但Json.NET似乎不支持這一點,至少從我看到的行爲來看。Json.NET可以在類中填充只讀字段嗎?

回答

-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); 
    } 
} 
+0

是的,這是我看到的相同的行爲。不幸的是,這與序列化對象的構造函數限制一樣,是Json.NET對我的破壞。 :( – 2010-11-17 20:34:30

+0

我的猜測是.net內置類有權訪問那些不可用於第三方庫的字段 – 2010-11-17 20:35:38

+0

它與使用反射設置任何其他字段沒有什麼不同,所以它是可行的,我已經提交了一個對Json.NET問題跟蹤器的功能請求 – asgerhallas 2011-07-07 07:35:36

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

這可以現在完成。使用JsonProperty屬性聲明你的屬性,並確保他們有一個保護套宣稱:

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

只有get使用時,這並沒有爲我工作,但與protected set完美。