2014-10-28 62 views
3

我想創建一個JSON的機器的目錄結構給定的所有文件和路徑的數組。如何將文件路徑的數組轉換爲分層的JSON結構

的陣列看起來是這樣的:

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" 
} 

目標JSON我瞄準的是這樣的:

{ 
    ".": 
    { 
     "file": 
     { 
      "name":"fileInRoot.xml" 
     }, 
     "proc": 
     { 
      "file": 
      { 
       "name":"fileInProc.xml" 
      }, 
      "15": 
      { 
       "file": 
       { 
        "name":"fileIn15.xml" 
       }, 
       "task": 
       { 
        "file": 
        { 
         "name":"fileInTask.xml" 
        }, 
        "15": 
        { 
         "file": 
         { 
          "name":"fileInTask.xml" 
         }, 
         "mounts": 
         { 
          "file": 
          { 
           "name":"fileInMounts.xml" 
          } 
         }, 
         "mountsInfo": 
         { 
          "file": 
          { 
           "name":"fileInMountsInfo.xml" 
          } 
         }, 
         "clear_refs": 
         { 
          "file": 
          { 
           "name":"fileInClear_Refs.xml" 
          } 
         }     
        } 
       } 
      }, 
      "14": 
      { 
       "file": 
       { 
        "name":"fileIn14.xml" 
       }, 
       "task": 
       { 
        "file": 
        { 
         "name":"fileInTask.xml" 
        }, 
        "loginUid": 
        { 
         "file": 
         { 
          "name":"fileInloginUid.xml" 
         }     
        }, 
        "sessionid": 
        { 
         "file": 
         { 
          "name":"fileInsessionid.xml" 
         }     
        }, 
        "coreDump_filter": 
        { 
         "file": 
         { 
          "name":"fileIncoreDump_filter.xml" 
         }     
        }, 
        "io": 
        { 
         "file": 
         { 
          "name":"fileInIo.xml" 
         }     
        } 
       } 
      } 
     } 
    } 
} 

我想創建一個JSON文件,允許消費者組件JSON來瀏覽這個目錄結構。我一直在嘗試使用Directory,FilePath類,但也許最好的方法是使用java.serializor(?)類構建JSON,並在我循環訪問數組時解析它的目錄和文件?

+0

您可以編輯,你的問題,以顯示你想創建JSON輸出的例子給出上面顯示的字符串數組? – 2014-10-28 19:20:38

+0

當然,如上所述,這將是一個很好的輸出。 – Fearghal 2014-10-29 12:05:25

+0

文件名從哪裏來?他們只是從目錄名(每個目錄一個文件)中假設? – 2014-10-29 12:09:20

回答

8

我想我會通過將其分成兩部分來解決這個問題。首先,我們需要一種解析目錄/文件路徑數組的方法,並將其放入分層結構中。其次,我們需要採取這種結構並將其轉變爲JSON。 (我是不是從你的問題串行你想使用哪個,所以這個答案我會認爲Json.Net是OK完全肯定。)

在第一部分,我會創造一個Dir類都有一個名字,一個兒童目錄的字典(爲了便於查找)和一組文件。我們可以在這個類中創建一個方法,它將解析一條路徑並查找或添加適當的子對象。

class Dir 
{ 
    public string Name { get; set; } 
    public Dictionary<string, Dir> Dirs { get; set; } 
    public HashSet<string> Files { get; set; } 

    public Dir(string name) 
    { 
     Name = name; 
     Dirs = new Dictionary<string, Dir>(); 
     Files = new HashSet<string>(); 
    } 

    public Dir FindOrCreate(string path, bool mightBeFile = true) 
    { 
     int i = path.IndexOf('/'); 
     if (i > -1) 
     { 
      Dir dir = FindOrCreate(path.Substring(0, i), false); 
      return dir.FindOrCreate(path.Substring(i + 1), true); 
     } 

     if (path == "") return this; 

     // if the name is at the end of a path and contains a "." 
     // we assume it is a file (unless it is "." by itself) 
     if (mightBeFile && path != "." && path.Contains(".")) 
     { 
      Files.Add(path); 
      return this; 
     } 

     Dir child; 
     if (Dirs.ContainsKey(path)) 
     { 
      child = Dirs[path]; 
     } 
     else 
     { 
      child = new Dir(path); 
      Dirs.Add(path, child); 
     } 
     return child; 
    } 
} 

使用這個類,我們可以很容易地通過在你的問題中給出的dirArray循環,使目錄層次:

Dir root = new Dir(""); 
foreach (string dir in dirArray) 
{ 
    root.FindOrCreate(dir); 
} 

所以在這一點上,root現在擁有整個目錄層次結構。如果你想,你可以直接使用Json.Net直接序列化這個對象來獲得合理的JSON結構。但是,它會比你在問題中描述的要冗長一點。這裏是會產生的JSON:

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

爲了讓你的目標的JSON,我們需要一個JsonConverter類:

class DirConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return (objectType == typeof(Dir)); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     Dir dir = (Dir)value; 
     JObject obj = new JObject(); 
     if (dir.Files.Count > 0) 
     { 
      JArray files = new JArray(); 
      foreach (string name in dir.Files) 
      { 
       files.Add(new JValue(name)); 
      } 
      obj.Add("list_of_files", files); 
     } 
     foreach (var kvp in dir.Dirs) 
     { 
      obj.Add(kvp.Key, JToken.FromObject(kvp.Value, serializer)); 
     } 
     obj.WriteTo(writer); 
    } 

    public override bool CanRead 
    { 
     get { return false; } 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

我們可以通過這樣的轉換序列化的目錄層次結構:

JsonSerializerSettings settings = new JsonSerializerSettings(); 
settings.Converters.Add(new DirConverter()); 
settings.Formatting = Formatting.Indented; 

string json = JsonConvert.SerializeObject(root, settings); 

這是輸出。請注意,我將原始JSON中的「文件」屬性更改爲數組,並將其重命名爲「list_of_files」,以適應每個目錄多個文件的可能性。我還假設永遠不會有一個名爲「list_of_files」的實際目錄。如果有這種可能性,則需要將文件數組的名稱更改爲不會與任何目錄名稱相沖突的其他名稱。 (如果您遇到一個錯誤,指出「Can not add property list_of_files to Newtonsoft.Json.Linq.JObject. Property with the same name already exists on object」,這意味着您的數據中有一個名稱爲「list_of_files」的目錄。)

{ 
    ".": { 
    "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" 
      ] 
     } 
     } 
    } 
    } 
} 

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

+0

哇,這看起來很棒,我會花一些時間查看它並整合並測試。我回來給你,當靜脈點擊做:) – Fearghal 2014-10-29 16:56:08

+0

嘿,布賴恩,我得到以下錯誤在JSON.Convert.Serialize(根,設置 - 不能添加屬性文件到Newtonsoft.Json.Linq.JObject。屬性具有相同的名稱已經存在於對象上。)我猜它的json有兩個同名的對象? – Fearghal 2014-10-30 13:42:30

+0

它的工作原理如果我序列化沒有'設置'var過載 – Fearghal 2014-10-30 14:22:28

相關問題