DEV Community

Ellis
Ellis

Posted on • Edited on

Flatten a json file: simple command line tool (Javascript)

For a long time I needed a simple utility to flatten json files, (so that I could do a "grep" for "basket.fruits.?.apple." for instance), but I couldn't find one like I wanted. The issue is, json objects are multi-line, and locating specific nodes is difficult with single-line search tools like grep. (Yes, there are some ways and tools for doing that.)

As json objects are natively supported in Javascript (json = JavaScript Object Notation, after all), I wanted to try writing one with js, which turned out to be quite easy to implement. It also uses recursion.

How to run the script from command line:

$ node json_flatten.js a.json

Then you can easily filter the output with "grep" to include or exclude certain keys or values, for instance.

The input file "a.json":

{
  "basket": {
    "fruitCount": 2,
    "fruits": [
      {
        "apple": {
          "colour": "red",
          "weight": "100g"
        }
      },
      {
        "pear": {
          "colour": "green",
          "weight": "150g"
        }
      }
    ]
  },
  "totalValue": "123.45"
}
Enter fullscreen mode Exit fullscreen mode

Output:

basket.fruitCount: 2
basket.fruits.0.apple.colour: red
basket.fruits.0.apple.weight: 100g
basket.fruits.1.pear.colour: green
basket.fruits.1.pear.weight: 150g
totalValue: 123.45
Enter fullscreen mode Exit fullscreen mode

The script:

// Example call from command line:
// $ node json_flatten.js a.json
// ------------------------------------
// GLOBALS:
const keyArray = [];

// ------------------------------------
// READ JSON FROM FILE:
// Note: do not import the json file directly,
// because if the file includes any js code,
// that will be executed too, which is a security risk.
if (process.argv.length < 3) {
  console.log("*** Error: specify a json file");
  process.exit(1);
}
const filename = process.argv[2];

const fs = require("fs");
const file = fs.readFileSync(filename, "utf8");
var json = JSON.parse(file);

// ------------------------------------
const printObjectEntries = (entries) => {
  for (let entry of entries) {
    const [key, value] = entry;

    if (typeof value !== "object" || value === null) {
      const keysPrefix = keyArray.length ? keyArray.join(".") + "." : "";
      console.log(keysPrefix + key + ":", value);
    } else {
      printObject(key, value);
    }
  }
};

// ------------------------------------
const printObject = (key, value) => {
  const entries = Object.entries(value);

  !!key && keyArray.push(key);
  printObjectEntries(entries);
  !!key && keyArray.pop();
};

// ------------------------------------
// MAIN:
printObject("", json);
Enter fullscreen mode Exit fullscreen mode

Top comments (0)