4

What is expected?:
I would like to convert the below listed directory structure into a single JSON file. The directory structure contains JSON files that are supposed to be included in the output file as well.

Limitations:
Node.js

Questions:
What would be a good/efficient way to generate the desired output, using Node.js + Modules? Logically, what would be the necessary steps?

Directory structure:

CMS/
├── en/
|   ├──brand_one/
|   |  ├──footer.json
|   |  ├──header.json
|   ├──brand_two/
|   |  ├──footer.json
|   |  ├──header.json
|   ├──brand_three/
|   |  ├──footer.json
|   |  ├──header.json
├── de/
|   ├──brand_one/
|   |  ├──footer.json
|   |  ├──header.json
|   ├──brand_two/
|   |  ├──footer.json
|   |  ├──header.json
|   ├──brand_three/
|   |  ├──footer.json
|   |  ├──header.json
├── fr/
|   ├──brand_one/
|   |  ├──footer.json
|   |  ├──header.json
|   ├──brand_two/
|   |  ├──footer.json
|   |  ├──header.json
|   ├──brand_three/
|   |  ├──footer.json
|   |  ├──header.json
├── es/
|   ├──brand_one/
|   |  ├──footer.json
|   |  ├──header.json
|   ├──brand_two/
|   |  ├──footer.json
|   |  ├──header.json
|   ├──brand_three/
|   |  ├──footer.json
|   |  ├──header.json

[...]

Desired output:

// content.json

{
  "en":[
    {
      "brand_one":{
        "footer":{
          "val": "value",
          [...]
        },
        "header":{
          "val": "value",
          [...]
        }
      },
      "brand_two":{
        "footer":{
          "val": "value",
          [...]
        },
        "header":{
          "val": "value",
          [...]
        }
      },
      "brand_three":{
        "footer":{
          "val": "value",
          [...]
        },
        "header":{
          "val": "value",
          [...]
        }
      }
    }
  ],
  [...]
}
1

3 Answers 3

3

You may use npm package tree-parser.

https://www.npmjs.com/package/tree-parser

Sign up to request clarification or add additional context in comments.

Comments

2

You could create a function to convert a directory to an object, with a property for each dir / file.

This would then be called recursively to walk the entire tree, in this case using the fs/promises functions.

const fs = require('fs/promises'); 
const path = require('path');

async function walkDir(dir, result = {}) {
    let list = await fs.readdir(dir);
    for(let item of list) {
        const itemPath = path.join(dir, item);
        let stats = await fs.stat(itemPath)
        if (await stats.isDirectory()) {
            result[item] = {};
            await walkDir(itemPath, result[item]);
        } else {
            const fileName = path.basename(item, path.extname(item));
            result[fileName] = JSON.parse(await fs.readFile(itemPath, { encoding: 'utf-8'}));
        }
    }
    return result;
}

async function testWalkDir() {
    let result = await walkDir('./CMS')
    console.log("Result:", JSON.stringify(result, null, 2));
}

testWalkDir();

Assuming each file looks like

{
  "some_key": "some_val"
}

I get a result that looks like so:

{
  "en": {
    "brand_one": {
      "footer": {
        "some_key": "some_val"
      },
      "header": {
        "some_key": "some_val"
      }
    },
    "brand_three": {
      "footer": {
        "some_key": "some_val"
      },
      "header": {
        "some_key": "some_val"
      }
    },
    "brand_two": {
      "footer": {
        "some_key": "some_val"
      },
      "header": {
        "some_key": "some_val"
      }
    }
  }
}


1 Comment

Thank you, this is the answer I was looking for.
1

You can try this module:

npm dree

Example code:

const dree = require('dree');

const options = {
    stat: false,
    normalize: true,
    followLinks: true,
    size: true,
    hash: true,
    depth: 5,
    exclude: /dir_to_exclude/,
    extensions: [ 'txt', 'jpg' ]
};

const tree = dree.scan('./folder', options);

There are lots of custom options, a result could be this:

{
  "name": "sample",
  "path": "D:/Github/dree/test/sample",
  "relativePath": ".",
  "type": "directory",
  "size": "1.81 MB",
  "children": [
    {
      "name": "backend",
      "path": "D:/Github/dree/test/sample/backend",
      "relativePath": "backend",
      "type": "directory",
      "size": "1.79 MB",
      "children": [
        {
          "name": "firebase.json",
          "path": "D:/Github/dree/test/sample/backend/firebase.json",
          "relativePath": "backend/firebase.json",
          "type": "file",
          "extension": "json",
          "size": "29 B"
        }, 
        {
          "name": "server",
          "path": "D:/Github/dree/test/sample/backend/server",
          "relativePath": "backend/server",
          "type": "directory",
          "size": "1.79 MB",
          "children": [
            {
              "name": "server.js",
              "path": "D:/Github/dree/test/sample/backend/server/server.js",
              "relativePath": "backend/server/server.js",
              "type": "file",
              "extension": "js",
              "size": "1.81 MB"
            }
          ]
        }
      ]
    }
  ]
}

Even a string could be returned, like this:

sample
 └─> backend
     ├── firebase.json
     ├── hello.txt
     └─> server
         └── server.js

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.