Skip to content
Advertisement

Node.js convert directory tree to JSON

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",
          [...]
        }
      }
    }
  ],
  [...]
}

Advertisement

Answer

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"
      }
    }
  }
}


User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement