2015-02-23 59 views
8

我使用Newtonsoft's JsonSerializer來連續化一些類。我如何「un-JsonIgnore」派生類中的屬性?

因爲我想忽略我的序列化過程類的一個領域,我宣佈它如下:

[JsonIgnore] 
public int ParentId { get; set; } 

這個工作,但我現在面臨一個新的問題:在派生類中,我希望此字段出現(並且在此特定的派生類中僅這樣做)。

我一直在瀏覽文檔,並在互聯網上的方式來覆蓋子類中的這種設置(我想我需要像[JsonStopIgnore],但我找不到任何關閉)。


  • 有什麼辦法,我強迫JsonSerializer再次拿起這個屬性?
  • 是否有可能在基類中明確標記屬性爲[JsonIgnore],但只有

回答

7

您可以通過創建自定義DefaultContractResolver並重寫其CreateProperty方法做到這一點。

例如,給定一個Foo基地和派生Bar

public class Foo 
{ 
    [JsonIgnore] 
    public string Name { get; set; } 
    public int Age { get; set; } 
} 

public class Bar : Foo 
{ } 

您可以創建以下合同解析:

public class MyTypeContractResolver<T> : DefaultContractResolver 
{ 
    protected override JsonProperty CreateProperty(MemberInfo member, 
                MemberSerialization 
                 memberSerialization) 
    { 
     var property = base.CreateProperty(member, memberSerialization); 

     property.Ignored = false; 
     property.ShouldSerialize = propInstance => property.DeclaringType != typeof (T); 
     return property; 
    } 
} 

這將所有屬性設置爲Ignored = false,然後分析它們由給定的謂詞:

propInstance => property.DeclaringType != typeof (T); 

在我們的情況下,這意味着「只有當它們不是Foo類型時才能序列化」(因爲Foo是DeclaryingType)。

然後當你要反序列化,你通過合同解析器的一個實例JsonSerializerSettings

var bar = new Bar(); 
var result = JsonConvert.SerializeObject(bar, 
    new JsonSerializerSettings {ContractResolver = new MyTypeContractResolver<Bar>()}); 
+0

感謝您對ContractResolver的解釋!如果我找不到更輕的解決方案,我會採用這種方式,至少可以進行嚴格的定製。 – PLNech 2015-02-23 13:37:16

+1

@PLNech當然可以。這絕對是「最重的」解決方案,但我認爲它也是使用Json.NET處理它的「正確」方式。 – 2015-02-23 13:39:04

+1

我很感激我現在有一個對「正確」方式的引用,如果我發現自己無法使用「懶惰」方式:P – PLNech 2015-02-23 13:40:51

3

您可能簡單地在派生類中覆蓋ParentId

public new int ParentId 
{ 
    get { return base.ParentId; } 
    set { base.ParentId = value; } 
} 
+1

但請注意,對基礎類的任何投射都將授予對隱藏屬性的訪問權限! – 2015-02-23 13:02:41

+1

@AndreasNiedermair是的。但我認爲,在使用Newtonsoft JSonSerializer進行序列化和反序列化時,它應該可以工作。對於剩餘的代碼,如果該屬性被繞過,那麼可以。 – xanatos 2015-02-23 13:05:37

9

只有這樣,才能「覆蓋」的[JsonIgnore]屬性的行爲是使用合同解析器,正如@Yuval Itzchakov在他的回答中很好地解釋的那樣。

然而,還有另一種可能爲你工作可能的解決方案:而不是使用[JsonIgnore]屬性,你可以實現你的班ShouldSerializeParentId()的方法來控制ParentId屬性是否被序列化。在基類中,使此方法返回false;然後覆蓋派生類中的方法返回true。 (這個特性在Json.Net中被稱爲conditional property serialization。)

public class Base 
{ 
    public int Id { get; set; } 
    public int ParentId { get; set; } 

    public virtual bool ShouldSerializeParentId() 
    { 
     return false; 
    } 
} 

public class Derived : Base 
{ 
    public override bool ShouldSerializeParentId() 
    { 
     return true; 
    } 
} 

小提琴:https://dotnetfiddle.net/65sCSz

+0

感謝您對我一無所知的機制的解釋! 儘管有點沉重,但這可能比使用自定義合約解析器實現相同結果更簡單的解決方案:) – PLNech 2015-02-24 09:31:17

+1

沒問題;樂意效勞。 – 2015-02-24 16:30:51

2

我通過使用派生類的屬性的新關鍵字解決同樣的問題。

public class Foo 
{ 
    [JsonIgnore] 
    public int ParentId { get; set; } 
} 

public class Bar: Foo 
{ 
    [JsonProperty("ParentId")] 
    public new int ParentId { get; set; } 
} 
+0

謝謝,很高興知道這是可能的。 – PLNech 2016-03-18 16:42:41

+0

我不知道爲什麼這個工作,但它確實。 我使用mongoDb保存對象後,現在拋出我的映射錯誤... – bonitzenator 2016-11-16 11:11:38

1

我解決了同樣的問題鬼屬性:

public class Foo 
{ 
    [JsonIgnore] 
    public int ParentId { get; set; } 

    [NotMapped] 
    public int FooParent { get; set; } 
} 

當我想告訴這個屬性相當總是隱藏,我填充它,其他時間爲空:

Foos.ForEach(x => x.FooParent = ParentId);