我正在尝试在给定其所有文件和路径的数组的情况下创建机器目录结构的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"
}
Run Code Online (Sandbox Code Playgroud)
我瞄准的目标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"
}
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想创建一个JSON文件,允许JSON的使用者组件浏览此目录结构.我一直在尝试使用Directory,File并Path类,但也许是最好的办法是使用java.serializor(?)类构建JSON通过数组我环路,解析它的目录和文件,因为我去?
我想我会把它分成两部分来解决这个问题.首先,我们需要一种方法来解析目录/文件路径数组并将其放入分层结构中.其次,我们需要采用该结构并将其转换为JSON.(我不完全确定你想要使用哪个序列化器,所以对于这个答案,我会假设Json.Net没问题.)
对于第一部分,我将创建一个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;
}
}
Run Code Online (Sandbox Code Playgroud)
使用这个类,我们可以轻松遍历dirArray您的问题中的给定并创建目录层次结构:
Dir root = new Dir("");
foreach (string dir in dirArray)
{
root.FindOrCreate(dir);
}
Run Code Online (Sandbox Code Playgroud)
所以在这一点上,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": []
}
Run Code Online (Sandbox Code Playgroud)
要获得您的目标,我们需要一个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();
}
}
Run Code Online (Sandbox Code Playgroud)
我们可以使用转换器序列化目录层次结构,如下所示:
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Converters.Add(new DirConverter());
settings.Formatting = Formatting.Indented;
string json = JsonConvert.SerializeObject(root, settings);
Run Code Online (Sandbox Code Playgroud)
这是输出.请注意,我将原始JSON中的"文件"属性更改为数组,并根据您的注释将其重命名为"list_of_files"以适应每个目录多个文件的可能性.我还假设永远不会有一个名为"list_of_files"的实际目录.如果可能,您需要将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"
]
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
小提琴:https://dotnetfiddle.net/ConJiu
| 归档时间: |
|
| 查看次数: |
1815 次 |
| 最近记录: |