Browse files

json 2.2.0: add '-e CODE' argument for input processing

  • Loading branch information...
1 parent 3bfbe0d commit 2480e73a3a0d437c364755df9fdca5a6660201dd @trentm committed Jan 5, 2012
Showing with 178 additions and 21 deletions.
  1. +10 −2 CHANGES.md
  2. +1 −1 LICENSE.txt
  3. +32 −0 README.md
  4. +27 −7 TODO.md
  5. +10 −0 json.1.ronn
  6. +29 −9 lib/jsontool.js
  7. +12 −1 man/man1/json.1
  8. +1 −1 package.json
  9. +39 −0 test/executable/cmd
  10. +17 −0 test/executable/expected.stdout
View
12 CHANGES.md
@@ -1,8 +1,16 @@
# json (aka jsontool) Changelog
-## json 2.1.1 (not yet released)
+## json 2.2.0 (not yet released)
+
+- New "-e CODE" option to execute the given code on the input object; or,
+ if '-a/--array' is given, then on each item in the input array. Execution
+ is done before filtering.
+
+ $ echo '{"age": 38}' | json -e 'this.age++'
+ {
+ "age": 39
+ }
-(nothing yet)
## json 2.1.0
View
2 LICENSE.txt
@@ -1,6 +1,6 @@
# This is the MIT license
-Copyright (c) 2011 Joyent Inc.
+Copyright (c) 2011-2012 Joyent Inc.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
View
32 README.md
@@ -43,6 +43,11 @@ You should now have "json" on your PATH:
make test
+You can also limit (somewhat) which tests are run with the `TEST_ONLY` envvar,
+e.g.:
+
+ cd test && TEST_ONLY=executable nodeunit test.js
+
I test against node 0.4, 0.5 and 0.6.
@@ -330,6 +335,33 @@ config files:
1
+# Executing code snippets on input
+
+You can use the `-e CODE` option to execute small code snippets to massage
+the input data. Some examples (generally use `this.<key>` to refer to a key):
+
+ $ echo '{"foo": "bar"}' | json -e 'this.foo="baz"'
+ {"foo":"baz"}
+
+Or omit the `this.` as a shortcut:
+
+ $ echo '{"foo": "bar"}' | json -e 'foo="baz"'
+ {"foo":"baz"}
+ $ echo '{"age": 38}' | json -e 'age++'
+ {"age":39}
+
+Set a key to `undefined` to remove it:
+
+ $ echo '{"one": 1, "two": 2}' | json -e 'this.one=undefined'
+ {"two":2}
+
+Arrays can be finnicky:
+
+ $ echo '[1,1]' | json -e 'this[0]++'
+ [2,1]
+ $ echo '["a", "b"]' | json -e 'this[3]="d"'
+ ["a","b",null,"d"]
+
# Module Usage
View
34 TODO.md
@@ -1,5 +1,6 @@
# top
+- 'make man'? Add to platform?
- edit support:
$ json -e foo=bar
{
@@ -42,15 +43,34 @@
{
"age": 38
}
- $ echo '[{"age":38}, {"age":21}]' | json -c 'this.age > 30'
+ $ echo '[{"age":38}, {"age": 42}, {"age":21}]' | json -a -c 'this.age > 30'
{
"age": 38
}
- # or this (???):
- [
- {
- "age": 38
- }
- ]
+ {
+ "age": 42
+ }
+
+
+echo '{"foo": "bar"}' | jsondev -e 'this.foo="baz"'
+ {
+ "foo": "baz"
+ }
+echo '{"age": 38}' | jsondev -e 'this.age++'
+ {
+ "age": 39
+ }
+
+echo '{"age": 38}' | jsondev -c 'this.age > 30'
+ {
+ "age": 38
+ }
+echo '[{"age":38}, {"age": 42}, {"age":21}]' | jsondev -a -c 'this.age > 30'
+ {
+ "age": 38
+ }
+ {
+ "age": 42
+ }
View
10 json.1.ronn
@@ -59,6 +59,16 @@ output:
Delimiter string for tabular output (default is ' ').
+You can process the input before filtering is done:
+
+`-e CODE`
+ Execute the given code on input, on each array item if '-a' is used.
+ Generally refer to a key as `this.<key>`.
+ If datum is an object, then a shortcut is `<key>`.
+ To remove a key, use `<key> = undefined`.
+ For array items: `this[<index>] = 42`.
+
+
Miscellaneous options:
`-h, --help`
View
38 lib/jsontool.js
@@ -5,11 +5,11 @@
// See <https://github.com/trentm/json>.
//
-var VERSION = "2.1.1";
+var VERSION = "2.2.0";
var util = require('util');
var pathlib = require('path');
-var runInNewContext = require('vm').runInNewContext;
+var vm = require('vm');
var warn = console.warn;
@@ -92,9 +92,9 @@ function printHelp() {
util.puts(" ...");
util.puts("");
util.puts(" # auto-arrayification")
- util.puts(" $ echo '{\"a\":1}{\"b\":2}' | json -o json-0");
+ util.puts(" $ echo '{\"a\":1}{\"b\":2}' | json");
util.puts(" [{\"a\":1},{\"b\":2}]");
- util.puts(" $ echo '[1,2][3,4]' | json -o json-0");
+ util.puts(" $ echo '[1,2][3,4]' | json");
util.puts(" [{\"a\":1},{\"b\":2}]");
util.puts("");
util.puts("Options:");
@@ -107,6 +107,10 @@ function printHelp() {
util.puts(" and output in tabular form");
util.puts(" -d DELIM delimiter string for tabular output (default is ' ')");
util.puts("");
+ util.puts(" -e CODE execute the given code on input, on each array item");
+ util.puts(" if '-a' is used. This execution is run before ");
+ util.puts(" filtering.");
+ util.puts("");
util.puts(" -o, --output MODE Specify an output mode. One of");
util.puts(" jsony (default): JSON with string quotes elided");
util.puts(" json: JSON output, 2-space indent");
@@ -137,6 +141,7 @@ function parseArgv(argv) {
help: false,
quiet: false,
dropHeaders: false,
+ executableSnippets: [],
outputMode: OM_JSONY,
jsonIndent: 2,
delim: ' '
@@ -215,6 +220,9 @@ function parseArgv(argv) {
case "-d":
parsed.delim = args.shift();
break;
+ case "-e":
+ parsed.executableSnippets.push(args.shift());
+ break;
default: // arguments
if (!endOfOptions && arg.length > 0 && arg[0] === '-') {
throw new Error("unknown option '"+arg+"'");
@@ -427,7 +435,7 @@ function lookupDatum(datum, lookup) {
lookupCode += '.' + lookup[i];
}
}
- return runInNewContext("(" + JSON.stringify(datum) + ")" + lookupCode);
+ return vm.runInNewContext("(" + JSON.stringify(datum) + ")" + lookupCode);
}
@@ -631,14 +639,20 @@ function main(argv) {
var lookups = lookupStrs.map(parseLookup);
var results = [];
if (opts.array) {
- var data = (isArray(input.datum) ? input.datum : [input.datum]);
if (lookups.length === 0) {
results = input.datum;
} else {
+ var data = (isArray(input.datum) ? input.datum : [input.datum]);
for (var j=0; j < data.length; j++) {
+ var datum = data[j];
+ for (var e=0; e < opts.executableSnippets.length; e++) {
+ var code = opts.executableSnippets[e];
+ vm.runInNewContext(code, datum);
+ }
+
var result = [];
for (var i=0; i < lookups.length; i++) {
- result.push(lookupDatum(data[j], lookups[i]));
+ result.push(lookupDatum(datum, lookups[i]));
}
results.push(result);
}
@@ -651,11 +665,17 @@ function main(argv) {
printDatum(row[c], opts, '\n', true);
});
} else {
+ var datum = input.datum;
+ for (var e=0; e < opts.executableSnippets.length; e++) {
+ var code = opts.executableSnippets[e];
+ vm.runInNewContext(code, datum);
+ }
+
if (lookups.length === 0) {
- results = input.datum;
+ results = datum;
} else {
for (var i=0; i < lookups.length; i++) {
- results.push(lookupDatum(input.datum, lookups[i]));
+ results.push(lookupDatum(datum, lookups[i]));
}
}
results.forEach(function (r) {
View
13 man/man1/json.1
@@ -1,7 +1,7 @@
.\" Generated with Ronnjs/v0.1
.\" http://github.com/kapouer/ronnjs/
.
-.TH "JSON" "1" "October 2011" "" ""
+.TH "JSON" "1" "January 2012" "" ""
.
.SH "NAME"
\fBjson\fR \-\- JSON love for your command line
@@ -78,6 +78,17 @@ output:
Delimiter string for tabular output (default is \' \')\.
.
.P
+You can process the input before filtering is done:
+.
+.P
+\fB\-e CODE\fR
+ Execute the given code on input, on each array item if \'\-a\' is used\.
+ Generally refer to a key as \fBthis\.<key>\fR\|\.
+ If datum is an object, then a shortcut is \fB<key>\fR\|\.
+ To remove a key, use \fB<key> = undefined\fR\|\.
+ For array items: \fBthis[<index>] = 42\fR\|\.
+.
+.P
Miscellaneous options:
.
.P
View
2 package.json
@@ -1,7 +1,7 @@
{
"name": "jsontool",
"description": "a 'json' command for massaging JSON on your Unix command line",
- "version": "2.1.1",
+ "version": "2.2.0",
"repository": {
"type": "git",
"url": "git://github.com/trentm/json.git"
View
39 test/executable/cmd
@@ -0,0 +1,39 @@
+JSON="../../lib/jsontool.js"
+JSON0="../../lib/jsontool.js -o json-0"
+
+echo '{"foo": "bar"}' | $JSON0 -e 'this.foo="baz"'
+# {"foo":"baz"}
+echo '{"foo": "bar"}' | $JSON0 -e 'foo="baz"'
+# {"foo":"baz"}
+echo '{"age": 38}' | $JSON0 -e 'this.age++'
+# {"age":39}
+echo '{"age": 38}' | $JSON0 -e 'age++'
+# {"age":39}
+
+echo '{"one": 1, "two": 2}' | $JSON0 -e 'this.one=undefined'
+# {"two":2}
+echo '{"one": 1, "two": 2}' | $JSON0 -e 'one=undefined'
+# {"two":2}
+
+echo '["a", "b"]' | $JSON0 -e 'this[0]="A"'
+# ["A","b"]
+echo '[1,1]' | $JSON0 -e 'this[0]++'
+# [2,1]
+echo '["a", "b"]' | $JSON0 -e 'this[3]="d"'
+# ["a","b",null,"d"]
+
+echo ''
+echo '{"one": 1, "two": 2}' | $JSON0 -e 'one++' -e 'two++'
+# {"one":2,"two":3}
+echo '{"one": 1, "two": 2}' | $JSON0 -e 'one++' one
+# 2
+
+echo ''
+echo '[{"first":"Trent","last":"Mick"},{"first":"Andrew","last":"Dlugan"}]' \
+ | $JSON0 -a -e 'name=[first,last].join(" ");first=undefined;last=undefined'
+# {"name":"Trent Mick"}
+# {"name":"Andrew Dlugan"}
+
+echo ''
+echo '{"foo": "bar"}' | $JSON -e 'foo foo' 2>&1 | grep SyntaxError
+# SyntaxError: Unexpected identifier
View
17 test/executable/expected.stdout
@@ -0,0 +1,17 @@
+{"foo":"baz"}
+{"foo":"baz"}
+{"age":39}
+{"age":39}
+{"two":2}
+{"two":2}
+["A","b"]
+[2,1]
+["a","b",null,"d"]
+
+{"one":2,"two":3}
+2
+
+{"name":"Trent Mick"}
+{"name":"Andrew Dlugan"}
+
+SyntaxError: Unexpected identifier

0 comments on commit 2480e73

Please sign in to comment.