0

With the following code:

static void Main(string[] args)
    {
        JObject fileSystemTree = CreateFileSystemJsonTree("C:/DirectoryTree");
        Console.WriteLine(fileSystemTree);
        Console.WriteLine("------");
        //
        //  Write it out to a file
        //
        System.IO.File.WriteAllText(@"C:\jsontree.txt", fileSystemTree.ToString());
        Console.ReadLine();
    }
    static JObject joNew = new JObject();
    static JObject CreateFileSystemJsonTree(string source)
    {
        //
        //  Build a list of all the IPs
        //
        //Console.WriteLine(source);
        using (var poiDbContext = new poiDbEntities())
        {
            DirectoryInfo di = new DirectoryInfo(source);
                {
                    joNew = new JObject(
                        new JProperty(di.Name, new JArray(Directory.GetDirectories(source).Select(d => CreateFileSystemJsonTree(d)))),
                        new JProperty("files", new JArray(di.GetFiles().Select(fi => new JObject(new JProperty(fi.Name, GetText(fi.Name)))))));
                }
                Console.WriteLine(joNew);
        }
        return joNew;
    }
    public static string GetText(string fiName)
    {
        using (var poiDbContext = new poiDbEntities())
        {
            string indexNameBody = fiName.Substring(0, fiName.LastIndexOf('.'));
            var indexResult = "test";  // dummied up for use by evaluators 
            return indexResult.Trim();
        }
    }

I am trying to create a filetree from a system directory using recursion. I have this working with XML but would prefer a JSON tree. The problem is that the txt files appear, not withing the Parent's [], which represents the lowest folder, but instead being added as JsonProperties with the text name I have added as "files"(which I don't want). Plus the "files" are generated even if there are no files, such as in an empty folder. The system generated snippet is followed by the a possible desired snippet.

"Sports": [
        {
          "NBA": [],
          "files": []  // Undesirable--The folder is empty`` 
        },``

The two snippets:

{  
      "Politics": [  
        {  
          "PresCandidates": [  
            {  
              "Republican": [],   // Notice the files are not in array   within the [] of the Republican    
              "files": [    
                {  
                  "carson_ben_s.txt": "Ben Carson"  
                },  
                {  
                  "trump_donald_j.txt": "Donald Trump"  
                },  
                {
                  "walker_scott_k.txt": "Scott Walker"  
                }  
              ]  
            }  
          ]  
        }  
      ],  
      "Politics": [  // The desired format
        {  
          "PresCandidates": [  
            {  
              "Republican": [  
                                {  
                                    "carson_ben_s.txt": "Ben Carson"  
                                },  
                                {  
                                    "trump_donald_j.txt": "Donald Trump"  
                                },  
                                {  
                                    "walker_scott_k.txt": "Scott Walker"  
                                }  
                            ],  

{

user3594395
  • 181
  • 4
  • 7

2 Answers2

0

I'm not sure I understand the JSON you want to create. If you're looking for a set of nested JSON objects where each property name corresponds to the file or directory name, and for a file, the property value is given by some callback method, while for a subdirectory, the value is an object recursively containing objects for all contents of the subdirectory, you could do this:

public static class DirectoryInfoExtensions
{
    public static JObject ToJson<TResult>(this DirectoryInfo info, Func<FileInfo, TResult> getData)
    {
        return new JObject
            (
            info.GetFiles().Select(f => new JProperty(f.Name, getData(f))).Concat(info.GetDirectories().Select(d => new JProperty(d.Name, d.ToJson(getData))))
            );
    }
}

And then use it like:

        string path = @"C:\Program Files (x86)\Microsoft Visual Studio 9.0";

        var di = new DirectoryInfo(path);
        Debug.WriteLine(di.ToJson(f => f.LastWriteTimeUtc));

Which produces output like:

{
  "redist.txt": "2007-10-16T21:56:34Z",
  "Common7": {
    "IDE": {
      "Brief.vsk": "2007-06-20T21:55:14Z",
      "WinFxCustomControlTemplateWizard.dll": "2008-07-30T14:06:58Z",
      "1033": {
        "cmddefui.dll": "2008-07-30T14:06:58Z",
        "Microsoft.VisualStudio.DesignUI.dll": "2008-07-30T14:06:58Z",
        "Microsoft.VisualStudio.EditorsUI.dll": "2008-07-30T14:06:58Z",

     Many values removed,

        "VsWizUI.dll": "2008-07-30T14:06:58Z",
        "WindowsFormsIntegration.PackageUI.dll": "2008-07-30T14:06:58Z"
      },
      "en": {
        "Microsoft.VisualStudio.Package.LanguageService.xml": "2007-03-02T04:30:40Z",
        "Microsoft.VisualStudio.Shell.Design.xml": "2007-03-06T04:40:44Z",
        "Microsoft.VisualStudio.Shell.xml": "2007-03-06T04:40:44Z"
      },
      "ExceptionAssistantContent": {
        "1033": {
          "DefaultContent.xml": "2007-09-03T05:11:44Z"
        }
      }
    }
  }
}

Is that what you want? Your partial JSON sample has arrays but I don't see where or how you need them.

If this is not what you want, could you clarify the desired JSON format somewhat?

By the way, if you have XML working, you could always use JsonConvert.SerializeXNode().

dbc
  • 104,963
  • 20
  • 228
  • 340
0

You idea worked beautifully. Thank you. I have one comment and a further question. I understand there is no standard format for a json file tree. However doesn't it make sense that each folder should be started and ended with [] because they are not "leaf" nodes? I tried to modify you code to make it look like the following but without success. I added the time stamp.

{ "7/28/2015 6:00:45 PM": // Modified by hand lennane_ava_l.txt": "Ava Lennane", "ALists": [ // Modified by hand "clinton_hillary_r.txt": "Hillary Clinton", "depasquale_vincent_99.txt": "Vincent Depasquale", "trump_donald_j.txt": "Donald Trump", "zz_kilroy_99.txt": "Kilroy", "Criminals": [], // Modified by hand "Entertainment": [], // Modified by hand "Politics": [ // Modified by hand "clinton_hillary_r.txt": "Hillary Clinton", "lennane_james_p.txt": "Jim Lennane", "trump_donald_j.txt": "Donald Trump", "PresCandidates": { // Unmodified "clinton_hillary_r.txt": "Hillary Clinton", "trump_donald_j.txt": "Donald Trump", "Democrat": { // Unmodified "clinton_hillary_r.txt": "Hillary Clinton" }, "Other": {}, "Republican": { "carson_ben_s.txt": "Ben Carson", "lennane_james_p.txt": "Jim Lennane", "trump_donald_j.txt": "Donald Trump", "walker_scott_k.txt": "Scott Walker"

user3594395
  • 181
  • 4
  • 7
  • Was this a reply to me? If so, it probably should have been a [comment](http://meta.stackexchange.com/questions/19756/how-do-comments-work) -- possibly on your own question with an "@dbc" inserted. – dbc Jul 30 '15 at 15:51
  • The JSON you propose is invalid according to the [standard](http://json.org/). JSON has two container constructs: arrays that look like `[value1, value2, ..., valueN]` and objects that look like `{"name1" : value1, "name2" : value2, ..., "nameN" : valueN }`. Your JSON has square brackets delimiting a set of name/value pairs, which is not allowed. – dbc Jul 30 '15 at 15:53
  • Thanks for the input. I using the solution you provided. As far as the incorrect use of "comments", I'll try to be more informed. – user3594395 Jul 31 '15 at 21:02