Skip to content

Instantly share code, notes, and snippets.

@jdp jdp/jp.js
Created Jun 29, 2011

Embed
What would you like to do?
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

This comment has been minimized.

Copy link
Owner Author

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
You can’t perform that action at this time.