Skip to content

Instantly share code, notes, and snippets.

@jdp
Created June 29, 2011 06:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdp/1053262 to your computer and use it in GitHub Desktop.
Save jdp/1053262 to your computer and use it in GitHub Desktop.
Manipulate JSON on the command line
#!/usr/bin/env node
var fs = require("fs");
var optimist = require("optimist");
function isArray(obj) {
return obj.constructor.toString().indexOf("Array") > -1;
}
function awk(IS, expr, options) {
var NR = IS.length;
var RS = [];
IS.forEach(function($0, $_) {
function $(i) { return $0[i]; }
(function() {
try {
eval("RS.push((function(){return ("+expr+")}).call($0));");
}
catch (e) {
console.log("error in Javascript expression for record", $_ + 1);
console.log(e.type, ":", e.arguments.join(","));
process.exit(2);
}
})();
});
if (options.json) {
process.stdout.write(JSON.stringify(RS));
}
else {
RS.forEach(function($0) {
process.stdout.write($0 + "\n");
});
}
}
function safeJsonParse(json) {
try {
var obj = JSON.parse(json);
return obj;
}
catch (e) {
console.log("invalid input JSON");
process.exit(1);
}
}
// Read a JSON string from standard input
function readFromStdin(cb) {
var buffer = "";
process.stdin.resume();
process.stdin.setEncoding("utf8");
process.stdin.on("data", function(chunk) {
buffer += chunk;
});
process.stdin.on("end", function() {
cb(safeJsonParse(buffer))
});
}
// Read a JSON string from file
function readFromFile(filename, cb) {
var data = fs.readFileSync(filename, "utf8");
cb(safeJsonParse(data));
}
// Parse command line, populate options, and act accordingly
argv = optimist
.usage("Manipulate JSON with Javascript expressions.")
.options("j", {
boolean: true,
})
.options("f", {
string: true,
alias: "file"
})
.argv;
(function() {
function dispatch($$) {
var expr = argv._.length ? argv._[0] : undefined;
awk(isArray($$) ? $$ : [$$], expr, {json: argv.j});
}
if (!!argv.f) {
readFromFile(argv.f, dispatch);
}
else {
readFromStdin(dispatch);
}
})();
# -j switch forces json output, -f specifies input file
~/P/js-awk> ./jp -j -f test.json 'this.user.friend_count > 100' && echo
[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false]
# leave off -f and take input from stdin
~/P/js-awk> cat test.json | ./jp -j 'this.user.friend_count > 100' && echo
[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false]
# leave off -j and you get output compatible with regular unix tools
~/P/js-awk> cat test.json | ./jp 'this.user.friend_count > 100' && echo
false
false
false
false
false
false
false
false
false
false
false
false
false
false
false
false
false
false
false
false
@jdp
Copy link
Author

jdp commented Jun 29, 2011

Lots of inspiration from jsawk, but greatly trimmed down. Stuff like null skipping is better solved by standard UNIX tools.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment