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"
}
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
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);
Top comments (0)