DevShadow DevShadow - 1 month ago 17
C# Question

C# Dynamically Map File System Using Recursion

I am trying to dynamically map a folder structure into JSON format using C#.

Here are my method:

public static string StartJson(string Dir)
{
try
{
StringBuilder Json = new StringBuilder();
Json.Append("{\"FileSystem\" : [");
if (Directory.GetDirectories(Dir).ToList().Count > 0)
{
Json.Append(GetDirectoryJson(Dir, 0));
}

if(Directory.GetFiles(Dir).ToList().Count > 0 && Directory.GetDirectories(Dir).ToList().Count == 0)
{
Json.Append(GetFileJSON(Dir));
}
else if(Directory.GetFiles(Dir).ToList().Count > 0 && Directory.GetDirectories(Dir).ToList().Count > 0)
{
Json.Append(",");
Json.Append("{");
Json.Append(GetFileJSON(Dir));
Json.Append("}");
}
Json.Append("]}");//Close FileSystem
return Json.ToString();
}
catch(Exception e) { return ""; }
}
public static int count = 0;
public static string GetDirectoryJson(string Dir, int Iteration)
{
try
{
string path1 = Directory.GetParent(Dir).FullName;
bool p = path.Equals(Directory.GetParent(Dir).FullName);
StringBuilder Json = new StringBuilder();
int folders = Directory.GetDirectories(path).ToList().Count;
foreach (string DirectoryPath in Directory.GetDirectories(Dir))
{

Json.Append("{");
Json.Append("\"Folder\": [{");
Json.Append("\"FolderPath\": " + "\"" + DirectoryPath.Replace('\\', '/') + "\"");
if(Directory.GetDirectories(DirectoryPath).ToList().Count > 0)
{
Json.Append(",");
Json.Append("\"Sub\": [");
count++;
Json.Append(GetDirectoryJson(DirectoryPath, Iteration++));
Json.Append("]");
}


if (Directory.GetFiles(DirectoryPath).ToList().Count > 0)
{
Json.Append(",");
Json.Append(GetFileJSON(Dir));
}
Json.Append("}");
Json.Append("]");
Json.Append("}");
}
return Json.ToString();
}
catch (Exception e) { return "Fail"; }
}

public static string GetFileJSON(string Dir)
{
try
{
StringBuilder Json = new StringBuilder();
Json.Append("\"Files\": [");
int FileCount = 0;
foreach (string FilePath in Directory.GetFiles(Dir))
{
Json.Append("{\"FilePath\": " + "\"" + FilePath.Replace('\\', '/') + "\"");
FileCount++;
if (Directory.GetFiles(Dir).ToList().Count == FileCount)
Json.Append("}");
else
Json.Append("},");
}
Json.Append("]");

return Json.ToString();
}
catch(Exception e) { return ""; }
}


I am getting really close, because this puts out MOSTLY correct JSON, when I use my test folder:
"C:\Users\sredmond.QPS_DOMAIN\Documents\Test"
I get the following JSON:

{
"FileSystem":[
{
"Folder":[
{
"FolderPath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1",
"Sub":[
{
"Folder":[
{
"FolderPath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files",
"Sub":[
{
"Folder":[
{
"FolderPath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/images",
"Files":[
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/CheckBrowser.js.download"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/footer_right.jpg"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/ga.js.download"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/igpnl_up.gif"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/ig_panel.css"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/ig_shared.css"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/jquery-1.9.0.min.js.download"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/jquery.browser.js.download"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/jquery.cookie.js.download"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/qps_logo.png"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/QPS_New.css"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/ScriptResource(1).axd"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/ScriptResource(2).axd"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/ScriptResource(3).axd"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/ScriptResource(4).axd"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/ScriptResource.axd"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/secondaryNavBG_right.jpg"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin_files/WebResource.axd"
}
]
}
]
}
],
"Files":[
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/CantLogin.html"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub1/UsersAndPass.csv"
}
]
}
]
}
],
"Files":[
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/New Hire Reporting Form - Copy.pdf"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/New Hire Reporting Form.pdf"
}
]
}
]
} {
"Folder":[
{
"FolderPath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub2",
"Sub":[
{
"Folder":[
{
"FolderPath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub2/Test",
"Files":[
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub2/UsersAndPass - Big (737).csv"
}
]
}
]
}
],
"Files":[
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/New Hire Reporting Form - Copy.pdf"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/New Hire Reporting Form.pdf"
}
]
}
]
} {
"Folder":[
{
"FolderPath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/Sub3"
}
]
},
{
"Files":[
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/New Hire Reporting Form - Copy.pdf"
},
{
"FilePath":"C:/Users/sredmond.QPS_DOMAIN/Documents/Test/New Hire Reporting Form.pdf"
}
]
}
]
}


As you can see the JSON is almost correct but there is no comma seperating the folders found at the Root. You can put the JSON in here: https://jsonformatter.curiousconcept.com/ and see for yourself where the errors occur.

Anyway, my question is how to I make it so that those commas are being put in the right spot. Every time I try to add a comma or put a conditional in it will put the comma in random spots in the JSON.

L.B L.B
Answer

Don't create a json by string operations...

I would create a custom class Folder and use a recursive method

public class Folder
{
    public string Path { set; get; }
    public List<string> Files { set; get; }
    public List<Folder> SubFolders { set; get; }

}

Folder GetFolderHierarchy(string root)
{
    var folder = new Folder();
    var dir = new DirectoryInfo(root);

    folder.Path = root;
    folder.Files =  dir.GetFiles().Select(x => x.FullName).ToList();

    folder.SubFolders = dir.GetDirectories().Select(x => GetFolderHierarchy(x.FullName))
                        .ToList();

    return folder;

}

Now, you can call it as

var folder = GetFolderHierarchy(@"d:\temp");
var json = JsonConvert.SerializeObject(folder, Newtonsoft.Json.Formatting.Indented);

ADDITION

In case you want to store relatetive paths instead of fullpath, the method can be changed to:

Folder GetFolderHierarchy(string root)
{
    var folder = new Folder();
    var dir = new DirectoryInfo(root);


    folder.Files = dir.GetFiles().Select(x => x.Name).ToList();
    folder.Path = dir.Name;
    folder.SubFolders = dir.GetDirectories().Select(x => GetFolderHierarchy(x.FullName))
                        .ToList();

    return folder;
}