2015-10-18 79 views
1

晚上好,C#.NET:反序列化JSON樹

對於我的具體問題,我要創建一個菜單(菜單的樹更準確)。因此,我決定使用複合設計模式具有以下結構:

  • IMenuComponent(接口定義一些性質等)
  • 菜單(包含IMenuComponent的列表)
  • MenuEntry(葉)

所以,我必須在知道備份方式的同時瀏覽它。顯而易見的答案是擁有「父母」財產。

我有以下的JSON樹:

{ 
    "Guid": "08967257-9306-4717-a76a-e1a4f0050505", 
    "Parent": null, 
    "Title": "Main Menu", 
    "Message": "A sample message", 
    "Elements": [ 
    { 
     "$type": "Menu", 
     "Guid": "26dfca59-9163-4b11-8033-e8ad13f3f5cc", 
     "Parent": "08967257-9306-4717-a76a-e1a4f0050505", 
     "Title": "Option 1", 
     "Message": "Another sample message", 
     "Elements": [ 
     { 
      "$type": "MenuEntry", 
      "Parent": "26dfca59-9163-4b11-8033-e8ad13f3f5cc", 
      "Title": "Entry 1", 
      "Message": "Another sample message" 
     }, 
     { 
      "$type": "MenuEntry", 
      "Parent": "26dfca59-9163-4b11-8033-e8ad13f3f5cc", 
      "Title": "Entry 2", 
      "Message": "Another sample message" 
     }, 
     { 
      "$type": "MenuEntry", 
      "Parent": "26dfca59-9163-4b11-8033-e8ad13f3f5cc", 
      "Title": "Entry 3", 
      "Message": "Another sample message" 
     } 
     ] 
    }, 
    { 
     "$type": "MenuEntry", 
     "Parent": "08967257-9306-4717-a76a-e1a4f0050505", 
     "Title": "Option 2", 
     "Message": "Another sample message" 
    } 
    ] 
} 

這不是反序列化本身,因爲這是工作,因爲它應該。

我的問題是,我有一個文件反序列化的「菜單」(根)後訪問的父母。 我能想到的方法有兩種:

  • 使用其GUID查找運行時「父」 - 可能是糟糕的表現明智根據樹的大小;
  • 添加一個「菜單」屬性都「菜單」和「MenuEntry」類存儲「父」,並填寫它,通過查找相應的GUID,從JSON反序列化之後。基本上,一旦應用程序啓動,我就把它放在一起,防止在運行時查找。這也可能是糟糕的表現。

什麼是要走的路?我該怎麼做?

作爲一個方面說明,我使用Newtonsoft.Json

感謝您的幫助!

+1

Guid在應用程序中有什麼含義嗎?或者它只是你的序列化邏輯的一部分?如果是後者,爲什麼要這樣做呢?樹結構已經在數據中固有;對它的第二個表示沒有什麼好處,可能與實際結構相沖突。 –

+0

儘管樹結構在數據中已經固有(甚至在反序列化之後),但知道「父」的唯一方法是存儲一個id,在這種情況下,它是Guid。有一個「菜單」類型的「父」會有循環引用,這是不可能序列化的第一個地方。但是,在我的帖子中指出,在反序列化之後填充該屬性是一種可能性。 – Apidcloud

+0

其實,在第二種選擇中,我必須通過整棵樹並比較Guid。由於我這樣做,我可以在不需要Guid的情況下即時存儲'Menu'屬性。我會試一試,稍後再發布結果。 – Apidcloud

回答

2

@Ian Mercer的評論實際上幫助我找出了一個簡單的解決方案(使用第二種方式在我上面的文章中描述)。

第二種方式並不真正依賴於Guid。在反序列化之後,我可以迭代每個菜單集合(因爲我可能會這樣做),並直接給出「父」的引用。

private void ConnectTree(Menu menu) 
{ 
    foreach (IMenuComponent component in menu.Elements) { 
     if (component is Menu) { 
      (component as Menu).ParentMenu = menu; 
      ConnectTree (component as Menu); 
     } 
     else if (component is MenuEntry) { 
      (component as MenuEntry).ParentMenu = menu; 
     } 
    } 
} 

只需要調用ConnectTree(_deserializedMenu)

編輯: @布賴恩羅傑斯剛纔提到從JSON淨PreserveReferencesHandling財產。最初的問題是關於json不支持循環引用,但解決了它 - 這與使用Guids的邏輯是一樣的。有多種解決方案,總是很好的知道。

謝謝!