2014-11-03 135 views
4

我的代碼的一部分以下面的格式將計算機的文件路徑序列化爲JSON。我正在努力接受這個JSON,並重新將文件路徑重新組合在一起。我正在使用Newtonsoft JSON庫;我發現它非常適合構建JSON。正如你所看到的,我的JSON嵌套了對象。如何反序列化未知對象結構的JSON對象

的JSON我有:

{ 
    ".": { 
    "proc": { 
     "15": { 
     "task": { 
      "15": { 
      "exe": {}, 
      "mounts": { 
       "list_of_files": [ 
       "mounts.xml" 
       ] 
      }, 
      "mountinfo": { 
       "list_of_files": [ 
       "mountinfo.xml" 
       ] 
      }, 
      "clear_refs": { 
       "list_of_files": [ 
       "clear_ref.xml" 
       ] 
      } 
      } 
     } 
     }, 
     "14": { 
     "loginuid": { 
      "list_of_files": [ 
      "loginuid.xml" 
      ] 
     }, 
     "sessionid": { 
      "list_of_files": [ 
      "sessionid.xml" 
      ] 
     }, 
     "coredump_filter": { 
      "list_of_files": [ 
      "coredump_filter.xml" 
      ] 
     }, 
     "io": { 
      "list_of_files": [ 
      "io.xml" 
      ] 
     } 
     } 
    } 
    } 
} 

數組我想從這個生成。

string[] dirArray = { 
"./proc/15/task/15/exe", 
"./proc/15/task/15/mounts/mounts.xml", 
"./proc/15/task/15/mountinfo/mountinfo.xml", 
"./proc/15/task/15/clear_refs/clear_ref.xml", 
"./proc/14/loginuid/loginuid.xml", 
"./proc/14/sessionid/sessionid.xml", 
"./proc/14/coredump_filter/coredump_filter.xml", 
"./proc/14/io/io.xml" 
} 

我的努力,我far--的deserialised JSON成一個動態的變量,但我不知道如何處理兩個問題:

  1. 我的JSON格式是未知的,我不知道物體有多深,我該如何處理?
  2. 如何在運行時定義動態變量時使用動態變量?

編輯

對不起,我原來的JSON格式是錯誤的,所以它不會與user12864提供的answer工作。我收到一個錯誤:Unable to cast object of type 'Newtonsoft.Json.Linq.JArray' to type 'Newtonsoft.Json.Linq.JObject'.

這是一個fiddle顯示我到目前爲止的位置。

+0

我可以建議你放棄所有的層次和而只是將每個路徑存儲爲完整的路徑? .NET中的'Path' API應足以確定代碼的層次結構。整個事情會更容易處理,並且由此產生的JSON將更具可讀性。 – mason 2014-11-03 15:39:08

+0

但是,如果我擁有的是json,我需要從中獲得路徑。也許我誤解你的評論? json首先的原因是允許UI消費者以可導航的方式顯示路徑。我現在編寫的代碼是要了解他們選擇保留哪些路徑,UI將編輯json併發送回去,爲了執行某些任務,我需要解構爲路徑。 – Fearghal 2014-11-03 15:39:50

+0

我在說你應該改變你的格式。只要它是一個JSON數組文件,不要以分層的方式存儲它。 – mason 2014-11-03 15:42:06

回答

2

@user12864在他的回答正確的想法,但需要調整代碼來解釋這樣一個事實,每個目錄下可以有文件的數組,而一個單一的「文件」對象(你原本應該在你的問題中提到過)。下面是一個更新的方法來處理:

private static void AddToFileList(JObject jo, List<string> list, string prefix) 
{ 
    foreach (var kvp in jo) 
    { 
     if (kvp.Key == "list_of_files") 
     { 
      foreach (string name in (JArray)kvp.Value) 
      { 
       list.Add(prefix + name); 
      } 
     } 
     else 
     { 
      JObject dir = (JObject)kvp.Value; 
      if (dir.Count == 0) 
      { 
       list.Add(prefix + kvp.Key); 
      } 
      else 
      { 
       AddToFileList(dir, list, prefix + kvp.Key + "/"); 
      } 
     } 
    } 
} 

完整的示例:

using System; 
using System.Collections.Generic; 
using Newtonsoft.Json; 
using Newtonsoft.Json.Linq; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     string json = @" 
     { 
      ""."": { 
      ""proc"": { 
       ""15"": { 
       ""task"": { 
        ""15"": { 
        ""exe"": {}, 
        ""mounts"": { 
         ""list_of_files"": [ 
         ""mounts.xml"" 
         ] 
        }, 
        ""mountinfo"": { 
         ""list_of_files"": [ 
         ""mountinfo.xml"" 
         ] 
        }, 
        ""clear_refs"": { 
         ""list_of_files"": [ 
         ""clear_ref.xml"" 
         ] 
        } 
        } 
       } 
       }, 
       ""14"": { 
       ""loginuid"": { 
        ""list_of_files"": [ 
        ""loginuid.xml"" 
        ] 
       }, 
       ""sessionid"": { 
        ""list_of_files"": [ 
        ""sessionid.xml"" 
        ] 
       }, 
       ""coredump_filter"": { 
        ""list_of_files"": [ 
        ""coredump_filter.xml"" 
        ] 
       }, 
       ""io"": { 
        ""list_of_files"": [ 
        ""io.xml"" 
        ] 
       } 
       } 
      } 
      } 
     }"; 

     JObject jo = JObject.Parse(json); 
     foreach (string path in CreateFileList(jo)) 
     { 
      Console.WriteLine(path); 
     } 
    } 

    private static List<string> CreateFileList(JObject jo) 
    { 
     List<string> ret = new List<string>(); 
     AddToFileList(jo, ret, ""); 
     return ret; 
    } 

    private static void AddToFileList(JObject jo, List<string> list, string prefix) 
    { 
     foreach (var kvp in jo) 
     { 
      if (kvp.Key == "list_of_files") 
      { 
       foreach (string name in (JArray)kvp.Value) 
       { 
        list.Add(prefix + name); 
       } 
      } 
      else 
      { 
       JObject dir = (JObject)kvp.Value; 
       if (dir.Count == 0) 
       { 
        list.Add(prefix + kvp.Key); 
       } 
       else 
       { 
        AddToFileList(dir, list, prefix + kvp.Key + "/"); 
       } 
      } 
     } 
    } 
} 

輸出:

./proc/15/task/15/exe 
./proc/15/task/15/mounts/mounts.xml 
./proc/15/task/15/mountinfo/mountinfo.xml 
./proc/15/task/15/clear_refs/clear_ref.xml 
./proc/14/loginuid/loginuid.xml 
./proc/14/sessionid/sessionid.xml 
./proc/14/coredump_filter/coredump_filter.xml 
./proc/14/io/io.xml 

小提琴:https://dotnetfiddle.net/r8CkI2

+0

那就是布萊恩。這是絕妙的,在示例json上學到的教訓,那是我的錯。你直接瞭解問題(儘管我),並且如此雄辯地解決它。 thx再次先生。我等了幾個小時,所以我可以添加一個賞金,然後標記爲已解決。 – Fearghal 2014-11-05 10:25:13

0

更新:


這裏是一個修改後的答案,你明確你的要求後:

The JavaScript Object Notation is built on the server, edited by user through a hierarchical tree interface component. That can be crawled incredibly easy.

因此,在本質您使用的組件,其中你希望建立簡單從組件派生的JavaScript對象表示法。您的用戶界面將是未知的,所以我會做出一些推定。

建立我們的目標:

public class XmlPath 
{ 
    public string Location { get; set; } 
} 

XmlPath將代表我們的對象。這將是基本的汽車財產。

將內容添加到我們的對象:

private List<XmlPath> AddXmlPath(List<string> location) 
{ 
    List<XmlPath> content = new List<XmlPath>(); 
    foreach(string item in location) 
      content.Add(new XmlPath() { Location = item }); 

    return content;   
} 

這將是令人難以置信的簡單方法,它將把你的用戶數據的大List<string>並將它們添加到您的XmlPath對象。從我們的對象

刪除內容:

private List<XmlPath> RemoveXmlPath(List<XmlPath> root, string location) 
{ 
    root.Remove(new XmlPath() { Location = location }); 
    return root; 
} 

這兩種方法確實不需要是,我只是演示和展示你怎麼可以。此外,它還會概述您實施起來的意圖。請注意,這是非常粗糙的做法。

序列化/反序列化我們的對象爲JavaScript異議符號:

JavaScriptSerializer serializer = new JavaScriptSerializer(); 
var xmlPath = AddXmlPath(List<string> location); 
var result = serializer.Serialize(xmlPath); 
var deserialize = serializer.Deserialize(List<XmlPath>>(result); 

我們的內容是通過一個基本的循環,現在暴露:

foreach(XmlPath item in deserialize) 
{ 
    // Exposed Model via 'item.Location' 
} 

你只需要這一核心功能關聯到你的實現。這種方法很粗糙,相當簡陋,肯定需要改進生產。然而,這應該讓你開始:

  • 序列化服務器上​​的數據。
  • 反序列化服務器數據。
  • 操作對象。

希望這對你更好。

+0

不是它的一個由用戶在分層樹接口組件中編輯的json(構建在服務器上)。因爲用戶可能會刪除json的任何節點(我使用json來允許輕鬆導航),所以我需要能夠抓取它的每個部分。該例子涵蓋了它可能的樣子。 – Fearghal 2014-11-03 17:39:57

+0

我已經爲你修改了我的答案。 – Greg 2014-11-03 18:56:02

2

這應該給你正在尋找什麼;只需創建一個JObjectJObject.Parse並傳遞給CreateFileList。它不會以任何不錯的方式處理格式錯誤的JSON。

static List<string> CreateFileList(JObject j) 
    { 
     List<string> ret = new List<string>(); 
     AddToFileList(j, ret, ""); 
     return ret; 
    } 


    static void AddToFileList(JObject j, List<string> dest, string prefix) 
    { 
     if (prefix.Length != 0) 
      prefix = prefix + '/'; 

     foreach (var kvp in j) 
     { 
      var jnext = (JObject)kvp.Value; 
      if (kvp.Key == "file") 
       dest.Add(prefix + (string)jnext["name"]); 
      else 
       AddToFileList(jnext, dest, prefix + kvp.Key); 
     } 
    } 

小提琴在https://dotnetfiddle.net/dQQ4tI

+0

Fantatsic,我得到一個錯誤,但是:無法轉換'Newtonsoft.Json.Linq.JValue'類型的對象鍵入'Newtonsoft.Json.Linq。JObject' – Fearghal 2014-11-03 16:10:30

+0

這種錯誤和其他類似的錯誤將發生在JSON上,並不完全匹配預期的佈局。我在你發佈的確切JSON文本上測試了這個確切的代碼,並且沒有錯誤。 – user12864 2014-11-03 16:19:45

+0

好的,我想我去搜索這個問題 – Fearghal 2014-11-03 16:27:46