# Json: folder tree recursively: Feedback please

**URL:** <https://discourse.processing.org/t/json-folder-tree-recursively-feedback-please/10542>\
**Category:** Coding Questions\
**Created:** [April 22, 2019, 1:29pm UTC](https://discourse.processing.org/t/json-folder-tree-recursively-feedback-please/10542 "2019-04-22T13:29:19Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [April 22, 2019, 1:29pm UTC](https://discourse.processing.org/t/json-folder-tree-recursively-feedback-please/10542/1 "2019-04-22T13:29:19Z")

</div>

Hello all,

I made a sketch where you can select a folder and it makes a json file with all folders recursively as children and sub-children.

Could somebody have a look and tell me whether that’s the proper way to do it?

for example, the children are just named 0,1,2…?

Thanks a lot!

Regards, Chrisir 😉

```auto
// user selects folder, all sub-folders are listed recursively in a json object

// **************************************************************
//// alter these values:
boolean SEARCH_RECURSIVE=true; // search sub-folders
// **************************************************************

//states 
final int stateWaitForFolder = 0; // consts  
final int stateDone = 1;
final int stateBreak = 2;  
int state = stateWaitForFolder; // current

String folderGlobal = "";  

DateTimeTool dateTimeTool=new DateTimeTool(); 

JSONObject targetFolder;

void setup() {
  size (1100, 700); 

  //targetFolder = new JSONObject();
  background(111);
  selectFolder("Select a folder to search sub-folders (Cancel to abort):", 
    "folderSelected");
}

void draw() {
  // 
  switch (state) {

  case stateWaitForFolder:

    // waiting until folder has been selected

    background(111);
    text("Please choose a folder. All sub-folders in the folder will be listed. Hit Cancel to abort.", 
      33, 33);    

    // THE WAIT IS OVER 
    if (!folderGlobal.equals("")) {
      targetFolder = searchFolder( folderGlobal, 0 ); 
      saveJSONObject(targetFolder, "data/list"+dateTimeTool.dateTimeStampShort()+".json");
      //
    } // if 
    break;

  case stateDone:
    background(111);
    text("DONE: " + folderGlobal + " (saved list to file).", 
      33, 33);
    showButtons();
    break;

  case stateBreak:
    background(111);
    text("Window was closed or the user hit cancel.", 33, 33); 
    showButtons(); 
    break; 

  default:
    // error
    println ("error 91"); 
    exit();
    break;
    //
  } // switch
} // func 

// -----------------------------------------------------------------------------

JSONObject searchFolder(String folderLocal, int depth) {
  // recursive 
  String[] strList; 

  // https://docs.oracle.com/javase/7/docs/api/java/io/File.html 
  // http://jsonviewer.stack.hu/ 
  // https://stackoverflow.com/questions/11194287/convert-a-directory-structure-in-the-filesystem-to-json-with-node-js

  File f = dataFile(folderLocal);

  JSONObject myFolder = new JSONObject();
  myFolder.setString("path", folderLocal);
  myFolder.setString("name", f.getName());
  myFolder.setString("type", "folder");

  // children 
  JSONArray values;
  values = new JSONArray();

  strList = f.list();
  if (strList!=null) {

    int i=0; 
    for (File f1 : f.listFiles()) {
      if (f1.isDirectory()) {
        JSONObject childFolder = new JSONObject();

        if (SEARCH_RECURSIVE)
          childFolder = searchFolder(f1.getAbsolutePath(), depth+1);

        values.setJSONObject(i, childFolder);
        i++;
      } //if
    } // for

    myFolder.setJSONArray( "children", values );

    state = stateDone; // next state
  } //if
  return myFolder;
} //func

String spaceSigns(int depth) {
  // makes indents 
  String newS="";
  for (int i=0; i<depth*4; i++) {
    newS+=" ";
  }
  return newS;
}//func

// -----------------------------------------------------------------
// file handling 

void folderSelected(File selection) {
  // the 'callback' function.
  if (selection == null) {
    println("Window was closed or the user hit cancel.");
    state=stateBreak;
  } else {
    println("User selected " + selection.getAbsolutePath());
    folderGlobal = selection.getAbsolutePath();
  } // else
}//func 

// ----------------------------------------------------------------
// Input 

void mousePressed() {
  if (state==stateDone||state==stateBreak) {
    if (dist(mouseX, mouseY, 133, 133) < 66) {
      // reset / restart
      folderGlobal=""; 
      selectFolder("Select a folder to list folders (Cancel to abort):", 
        "folderSelected");
      state=stateWaitForFolder;
    }//if
    else if (dist(mouseX, mouseY, 233, 133) < 66) {
      exit();
    }//else if
  }//if
}//func 

//-------------------------------------------------------------------
//Tools

void showButtons() {
  // set mode for text and rect 
  textAlign(CENTER, CENTER);
  rectMode(CENTER);

  // rects 
  noFill();  
  rect(133-5, 133+3, 84, 23);
  rect(233-1, 133+3, 84, 23);

  // text 
  fill(255); 
  text ( "Next folder", 133, 133);
  text ( "Quit", 233, 133);

  // reset 
  textAlign(LEFT);
  rectMode(CORNER); // The default mode is rectMode(CORNER)
}//func 
//

// ============================================================================
// minor class to get a date-time-stamp from. 

class DateTimeTool {

  String dateTimeStampShort() {
    // short version 
    return getDate() + "_" + getTime();
  }

  String dateTimeStampLong() {
    // long version 
    return getDateLong()
      + " at " 
      + getTimeLong();
  }

  //-----

  String getTime() {
    return leadingZeros(hour()) 
      + leadingZeros(minute()) 
      + leadingZeros(second());
  }

  String getTimeLong() {
    return leadingZeros(hour()) 
      +":"+ leadingZeros(minute()) 
      +":"+ leadingZeros(second());
  }

  String getDate() {
    return leadingZeros(year()) 
      + leadingZeros(month()) 
      + leadingZeros(day());
  }

  String getDateLong() {
    return leadingZeros(year()) 
      +"/"+ leadingZeros(month()) 
      +"/"+ leadingZeros(day());
  }

  //-----

  String leadingZeros(int a) {
    String Buffer;
    Buffer=nf(a, 2);
    return(Buffer);
  }
  //
}//class
//

```

* * *

the sketch saves:

```auto

{
  "path": "C:\\Users\\Christoph\\Documents\\pTest",
  "children": [
    {
      "path": "C:\\Users\\Christoph\\Documents\\pTest\\autumn",
      "children": [],
      "name": "autumn",
      "type": "folder"
    },
    {
      "path": "C:\\Users\\Christoph\\Documents\\pTest\\spring",
      "children": [],
      "name": "spring",
      "type": "folder"
    },
    {
      "path": "C:\\Users\\Christoph\\Documents\\pTest\\summer",
      "children": [
        {
          "path": "C:\\Users\\Christoph\\Documents\\pTest\\summer\\Surf2",
          "children": [],
          "name": "Surf2",
          "type": "folder"
        },
        {
          "path": "C:\\Users\\Christoph\\Documents\\pTest\\summer\\Surfing1",
          "children": [],
          "name": "Surfing1",
          "type": "folder"
        }
      ],
      "name": "summer",
      "type": "folder"
    },
    {
      "path": "C:\\Users\\Christoph\\Documents\\pTest\\winter",
      "children": [
        {
          "path": "C:\\Users\\Christoph\\Documents\\pTest\\winter\\Ski",
          "children": [],
          "name": "Ski",
          "type": "folder"
        },
        {
          "path": "C:\\Users\\Christoph\\Documents\\pTest\\winter\\Ski2",
          "children": [],
          "name": "Ski2",
          "type": "folder"
        },
        {
          "path": "C:\\Users\\Christoph\\Documents\\pTest\\winter\\Snowboard",
          "children": [
            {
              "path": "C:\\Users\\Christoph\\Documents\\pTest\\winter\\Snowboard\\1",
              "children": [],
              "name": "1",
              "type": "folder"
            },
            {
              "path": "C:\\Users\\Christoph\\Documents\\pTest\\winter\\Snowboard\\2",
              "children": [],
              "name": "2",
              "type": "folder"
            }
          ],
          "name": "Snowboard",
          "type": "folder"
        }
      ],
      "name": "winter",
      "type": "folder"
    }
  ],
  "name": "pTest",
  "type": "folder"
}

```

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [April 26, 2019, 10:03am UTC](https://discourse.processing.org/t/json-folder-tree-recursively-feedback-please/10542/2 "2019-04-26T10:03:30Z")

</div>

Hi @Chrisir – when you say

> [@Chrisir](#):
>
> Could somebody have a look and tell me whether that’s the proper way to do it?

what is your goal for the code? For example, JSON can store a set of nested objects (like files / folders) in an ordered (array) or unordered (object) way.

[https://www.json.org/](https://www.json.org/)

Is there a particular sort order that you would want, e.g. by filename / type / date, or does that not matter?

You might also be interested in this related question / answer. It is a fixed depth hack that doesn’t give a full recursive solution like yours, but an interesting point of reference. Maybe you should post a Java version your solution there when you are done with it…

> <https://stackoverflow.com/questions/44366518/reading-the-directory-structure-and-converting-it-into-json-object-in-java/44457821#44457821>

If you are thinking about adding file metadata like modified data (and created date if available), here is a Java 7 example with File:

> <https://stackoverflow.com/questions/2723838/determine-file-creation-date-in-java/2724009#2724009>

---

<div class="post-metadata">

**Author:** ![kfrajer](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kfrajer/32/196_2.png) [@kfrajer](https://discourse.processing.org/u/kfrajer)\
**Post date:** [April 27, 2019, 8:38am UTC](https://discourse.processing.org/t/json-folder-tree-recursively-feedback-please/10542/3 "2019-04-27T08:38:55Z")

</div>

I can think this concept could be useful to make available the files and folder structure to a program. With this information, one could display the actual data (similar to the **tree** command in the command prompt in Windows) or a programmer could use it for its own projects to load all the [selected] resources from a folder location. Using the json structure, it would be easy to add and customize metadata fields associated to each file making this very handy in certain use cases.

Kf
