2017-10-16 80 views
1

我有一個JSON結構(包括POCO類)與親子關係的孩子的對象數組是這樣的:存儲/檢索與JsonConverter

 

    "Object": [ 
    { 
     "Name": "TestA", 
     "ChildObjects": [ 
     { 
      "Name": "TestB" 
      "ChildObjects": [ 
       { 
        "Name": "TestC" 
        ... 
       } 
      ] 
     } 
    ] 

反序列化的時候,我想引用保持父 我剛剛創建的對象。

但是我必須在填充子對象之前得到這個引用(當我填充子對象時,我必須有父對象結構/引用可訪問)

我試過使用自定義的JsonConverter,但是 我找不到存儲或檢索這種關係的方法。

+1

您是否嘗試將['PreserveReferencesHandling'](https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_PreserveReferencesHandling.htm)設置設置爲'Objects'?如果你這樣做,你不應該需要一個轉換器;引用將通過特殊的'$ id'和'$ ref'元屬性保存在JSON中。 –

+0

@BrianRogers,我想過爲「Object Class」添加一個「Parent Object」屬性。這樣我就可以得到父母的參考。這個參考資料是否適合這種用途? (如果它可以作爲JSON文件上父節點的引用) –

+0

是的,您的子對象可以引用父對象,反之亦然,如果您在序列化和反序列化時都使用該設置,它應該可以工作。 –

回答

0

你不需要JsonConverter。

您可以創建表示JSON,下面給出的POCO類:

public class OstacolisRuntime 
    { 
     public int CodiceOstacolo { get; set; } 
     public int TipoOstacolo { get; set; } 
     public int Tipologia { get; set; } 
     public string Nome { get; set; } 
     public double PosizioneX { get; set; } 
     public double PosizioneY { get; set; } 
     public double PosizioneZ { get; set; } 
     public double AngoloX { get; set; } 
     public double AngoloY { get; set; } 
     public double AngoloZ { get; set; } 
     public double ScalaX { get; set; } 
     public double ScalaY { get; set; } 
     public double ScalaZ { get; set; } 
     public List<SubOggetto> SubOggettos { get; set; } //sub 
    } 




    public class SubOggetto 
    { 
     public string Immagine { get; set; } 
     public int Tipologia { get; set; } 
     public string Nome { get; set; } 
     public double PosizioneX { get; set; } 
     public double PosizioneY { get; set; } 
     public double PosizioneZ { get; set; } 
     public double AngoloX { get; set; } 
     public double AngoloY { get; set; } 
     public double AngoloZ { get; set; } 
     public double ScalaX { get; set; } 
     public double ScalaY { get; set; } 
     public double ScalaZ { get; set; } 
     public List<SubOggetto> SubOggettos { get; set; } //recursive relashioship 
    } 


    public class RootObject 
    { 
     public List<OstacolisRuntime> OstacolisRuntime { get; set; } 
    } 

反序列化您JSON:

var o= JsonConvert.DeserializeObject<RootObject>(json); 

您可以檢查complete source code

+0

M.哈桑。我已經有了這些課程。反序列化時,我必須找到一種方法來獲得這種關係。子節點必須能夠在反序列化中知道父節點。 –

0

而不是定義這是一個序列化問題(如何序列化和反序列化對父代的反向引用),將其定義爲類設計問題可能是有意義的,即

由於家長和孩子的層次結構,如何保證孩子的父母背引用自動將其添加到他們的父母時設置是否正確?

一旦以這種方式定義問題並解決問題,在反序列化和程序化數據創建期間應保證正確性,因爲父反向引用永遠不需要序列化或反序列化。

完成此操作的一種方法是定義一個自定義子類Collection<T>,該子類自動設置並清除父回引用。

首先,定義以下接口和收集:

public interface IHasParent<TParent> where TParent : class 
{ 
    TParent Parent { get; } 

    void OnParentChanging(TParent newParent); 
} 

public class ChildCollection<TParent, TChild> : Collection<TChild> 
    where TChild : IHasParent<TParent> 
    where TParent : class 
{ 
    readonly TParent parent; 

    public ChildCollection(TParent parent) 
    { 
     this.parent = parent; 
    } 

    protected override void ClearItems() 
    { 
     foreach (var item in this) 
     { 
      if (item != null) 
       item.OnParentChanging(null); 
     } 
     base.ClearItems(); 
    } 

    protected override void InsertItem(int index, TChild item) 
    { 
     if (item != null) 
      item.OnParentChanging(parent); 
     base.InsertItem(index, item); 
    } 

    protected override void RemoveItem(int index) 
    { 
     var item = this[index]; 
     if (item != null) 
      item.OnParentChanging(null); 
     base.RemoveItem(index); 
    } 

    protected override void SetItem(int index, TChild item) 
    { 
     var oldItem = this[index]; 
     if (oldItem != null) 
      oldItem.OnParentChanging(null); 
     if (item != null) 
      item.OnParentChanging(parent); 
     base.SetItem(index, item); 
    } 
} 

然後定義您的MyObjectRootObject類型如下:

public class MyObject : IHasParent<MyObject> 
{ 
    readonly ChildCollection<MyObject, MyObject> childObjects; 

    public MyObject() { this.childObjects = new ChildCollection<MyObject, MyObject>(this); } 

    public string Name { get; set; } 

    public IList<MyObject> ChildObjects { get { return childObjects; } } 

    #region IHasParent<MyObject> Members 

    [JsonIgnore] 
    public MyObject Parent { get; private set; } 

    public void OnParentChanging(MyObject newParent) 
    { 
     Parent = newParent; 
    } 

    #endregion 

    // Added to suppress serialization of empty ChildObjects collections to JSON. 
    public bool ShouldSerializeChildObjects() { return childObjects.Count > 0; } 
} 

public class RootObject 
{ 
    public RootObject() { this.Object = new List<MyObject>(); } 

    public List<MyObject> Object { get; set; } 
} 

注:

  • 收集IList<MyObject> ChildObjectsMyObject是啓動LY。 Json.NET(和XmlSerializer就此而言)可以成功反序列化一個只能獲得預分配的集合。

  • 方法ShouldSerializeChildObjects()是可選的,並防止對空的ChildObjects []數組值進行序列化。

  • 由於ObservableCollection<T>本身就是Collection<T>一個子類,你可以選擇它作爲基類爲ChildCollection<TParent, TChild>,如果你需要通知項目時添加或刪除。

  • Parent屬性標有[JsonIgnore]以防止其序列化。

樣本fiddle包括一些基本的單元測試。