Comparing version 0.0.14 to 8.0.0
@@ -1,17 +0,28 @@ | ||
{ "name": "json" | ||
, "version": "0.0.14" | ||
, "engines": [ "node >=0.4.0" ] | ||
, "description": "JSON command line processing toolkit." | ||
, "author": "Zachary Poley <zpoley@gmail.com> (http://zpoley.net)" | ||
, "contributors": [ "Isaac Schlueter <i@izs.me> (http://blog.izs.me)", "Andrey Tarantsov <andreyvit@gmail.com> (http://www.tarantsov.com/)", "Niek Schmoller <niek.schmoller@helderberg.nl> (http://helderberg.nl)", "Ryunosuke SATO (http://d.hatena.ne.jp/tricknotes/)", "Johan Sundström (http://ecmanaut.blogspot.com/)" ] | ||
, "keywords" : [ "json", "command", "shell" ] | ||
, "man" : "./man/json.1" | ||
, "repository": | ||
{ "type" : "git" | ||
, "url" : "https://github.com/zpoley/json-command.git" | ||
{ | ||
"name": "json", | ||
"description": "a 'json' command for massaging and processing JSON on the command line", | ||
"version": "8.0.0", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/trentm/json.git" | ||
}, | ||
"author": "Trent Mick <trentm@gmail.com> (http://trentm.com)", | ||
"main": "./lib/json.js", | ||
"directories": { | ||
"man": "./man/man1" | ||
}, | ||
"bin": { "json": "./lib/json.js" }, | ||
"scripts": { | ||
"test": "make test" | ||
}, | ||
"engines": ["node >=0.4.0"], | ||
"keywords": ["json", "jsontool", "filter", "command", "shell"], | ||
"devDependencies": { | ||
"uglify-js": "1.1.x", | ||
"nodeunit": "0.8.x", | ||
"ansidiff": "1.0", | ||
"ben": "0.0.x", | ||
"async": "0.1.22", | ||
"semver": "1.1.0" | ||
} | ||
, "bin" : { "json" : "./bin/json.js" } | ||
, "scripts": | ||
{ "test" : "node test/test.js" | ||
} | ||
} |
170
README.md
@@ -1,133 +0,119 @@ | ||
# JSON Command | ||
`json` is a fast CLI tool for working with JSON. It is a single-file node.js | ||
script with no external deps (other than | ||
[node.js](https://github.com/joyent/node) itself). A quick taste: | ||
JSON command line processing toolkit. | ||
$ echo '{"foo":"bar"}' | json | ||
{ | ||
"foo": "bar" | ||
} | ||
no more writing code to inspect or transform JSON objects. | ||
$ echo '{"foo":"bar"}' | json foo | ||
bar | ||
this npm module includes a json shell command. the json command processes standard | ||
input and parses json objects. json currently handles a few different standard | ||
input formats and provides a number of options tailored toward inspecting and | ||
transforming the parsed json objects. | ||
$ echo '{"age":10}' | json -E 'this.age++' | ||
{ | ||
"age": 11 | ||
} | ||
## IMPORTANT | ||
$ echo '{"latency":32,"req":"POST /widgets"}, | ||
{"latency":10,"req":"GET /ping"} | ||
' | json -gaC 'this.latency > 10' req | ||
POST /widgets | ||
json-command has been renamed to json in npm. all updates will be made to the json npm package. | ||
Features: | ||
you need node v0.4.0 or higher and npm to run this program. | ||
- pretty-printing JSON | ||
- natural syntax (like JS code) for extracting particular values | ||
- get details on JSON syntax errors (handy for config files) | ||
- filter input JSON (see `-E` and `-C` options) | ||
- fast stream processing | ||
- JSON validation | ||
- in-place file editing | ||
## Installation | ||
See <http://trentm.com/json> for full docs and examples as a man page. | ||
npm install json | ||
Follow <a href="https://twitter.com/intent/user?screen_name=trentmick" target="_blank">@trentmick</a> | ||
for updates to json. | ||
installs json shell command. | ||
## Examples | ||
# Installation | ||
the following examples parse json output from twitter http requests and output the | ||
requested json fields. | ||
1. Get [node](http://nodejs.org). | ||
please note that the last two examples require you to enter your username and password. | ||
2. `npm install -g json` | ||
curl http://search.twitter.com/search.json?q=node.js | ||
*Note: This used to be called 'jsontool' in the npm registry, but as of | ||
version 8.0.0 it has taken over the 'json' name. See [npm Package | ||
Name](#npm-package-name) below.* | ||
curl -s http://search.twitter.com/search.json?q=node.js | json | ||
**OR manually**: | ||
curl -s http://search.twitter.com/search.json?q=node.js | json -o results | ||
2. Get the 'json' script and put it on your PATH somewhere (it is a single file | ||
with no external dependencies). For example: | ||
curl -s http://search.twitter.com/search.json?q=node.js | json -o results from_user metadata | ||
cd ~/bin | ||
curl -L https://github.com/trentm/json/raw/master/lib/json.js > json | ||
chmod 755 json | ||
curl -s http://search.twitter.com/search.json?q=node.js | json -o results new_id=id | ||
You should now have "json" on your PATH: | ||
curl -s http://search.twitter.com/search.json?q=node.js | json -o results -C from_user from_user_id | ||
$ json --version | ||
json 7.0.0 | ||
curl -s http://stream.twitter.com/1/statuses/sample.json -uAnyTwitterUser:Password | json user.name user.id | ||
curl -s http://stream.twitter.com/1/statuses/sample.json -uAnyTwitterUser:Password | json user.name user.id -c "entities.user_mentions.length > 0" | ||
**WARNING for Ubuntu/Debian users:** There is a current bug in Debian stable | ||
such that "apt-get install nodejs" installed a `nodejs` binary instead of a | ||
`node` binary. You'll either need to create a symlink for `node`, change the | ||
`json` command's shebang line to "#!/usr/bin/env nodejs" or use | ||
[chrislea's PPA](https://launchpad.net/~chris-lea/+archive/node.js/) as | ||
discussed on [issue #56](https://github.com/trentm/json/issues/56). | ||
## Synopsis | ||
json [options] [fields] | ||
# Test suite | ||
## Options | ||
make test | ||
-h print help info and exit | ||
You can also limit (somewhat) which tests are run with the `TEST_ONLY` envvar, | ||
e.g.: | ||
-v (-V | --version) print version number and exit | ||
cd test && TEST_ONLY=executable nodeunit test.js | ||
-u print ugly json output, each object on a single line | ||
I test against node 0.4 (less so now), 0.6, 0.8, and 0.10. | ||
-d print debugging output including exception messages | ||
-o object.path specify the path to an array to be iterated on | ||
# License | ||
new.key=old_key move old_key to new.key in output object | ||
MIT (see the fine LICENSE.txt file). | ||
-a input object is an array, process each element separately | ||
-c "js conditional" js conditional to be run in the context of each object that determines whether an object is printed | ||
# Module Usage | ||
-C print the output fields as tab delimited columns in the order specified by fields | ||
Since v1.3.1 you can use "json" as a node.js module: | ||
-e "js expression" execute arbitrary js in the context of each object. | ||
var json = require('json'); | ||
-i use node's util.inspect instead of JSON.stringify. | ||
However, so far the module API isn't that useful and the CLI is the primary | ||
focus. | ||
-H print headers, if they are supplied. Useful for output from curl -i. | ||
# npm Package Name | ||
## Fields | ||
Once upon a time, `json` was a different thing (see [zpoley's json-command | ||
here](https://github.com/zpoley/json-command)), and this module was | ||
called `jsontool` in npm. As of version 8.0.0 of this module, `npm install json` | ||
means this tool. | ||
any number of fields can be specified to be printed from each json object. | ||
by default the structure of the original json object is maintained, however options | ||
like -e and foo=bar allow for transforming object structure. | ||
If you see documentation referring to `jsontool`, it is most likely | ||
referring to this module. | ||
to remove a particular key, assign it to undefined using the -e flag. | ||
## Standard Input Formats | ||
# Alternatives you might prefer | ||
* line delimited json objects | ||
* back to back json objects. | ||
e.g. { obj1 : body }{ obj2 : body } | ||
* file separated json objects. | ||
e.g. cat files/* | json | ||
* when using -a, a single JSON array | ||
## Order of operations | ||
1. objects are parsed from stdin | ||
2. any non-existing requested keys are instantiated | ||
3. key transforms are applied to the object | ||
4. expressions are run against the object | ||
5. conditionals are checked against the object. the object is discarded if conditionals do not pass | ||
6. the requested keys are pulled from the object and output | ||
## Limitations | ||
* all input is handled through standard in | ||
* the current version is not particularly slow, but is NOT optimized for speed in any way | ||
## Documentation | ||
the npm package includes a man page that can be accessed using: | ||
man json | ||
## Known Issues | ||
this is alpha quality code, so use at your own risk. | ||
## Thanks | ||
this project respectfully uses code from and thanks the authors of: | ||
* [node](http://github.com/ry/node) | ||
* [npm](http://npmjs.org/) | ||
- jq: <http://stedolan.github.io/jq/> | ||
- json:select: <http://jsonselect.org/> | ||
- jsonpipe: <https://github.com/dvxhouse/jsonpipe> | ||
- json-command: <https://github.com/zpoley/json-command> | ||
- JSONPath: <http://goessner.net/articles/JsonPath/>, <http://code.google.com/p/jsonpath/wiki/Javascript> | ||
- jsawk: <https://github.com/micha/jsawk> | ||
- jshon: <http://kmkeen.com/jshon/> | ||
- json2: <https://github.com/vi/json2> |
302
test/test.js
@@ -1,165 +0,179 @@ | ||
var assert = require("assert"), | ||
jsonCommand = require("../lib/jsonCommand"); | ||
/** | ||
* 'json' test suite | ||
* | ||
* Usage: | ||
* nodeunit test.js | ||
* | ||
* Can limit the tests with the 'TEST_ONLY' environment variable: a | ||
* space-separated lists of dir names to which to limit. E.g.: | ||
* TEST_ONLY=hello-server nodeunit test.js | ||
* Can also prefix with a '-' to *exclude* that test. E.g.: to run all but | ||
* the 'irc' test: | ||
* TEST_ONLY='-irc' nodeunit test.js | ||
*/ | ||
var testObj = { | ||
id : 19375093, | ||
text : "who knows", | ||
user : { | ||
id : 1310571, | ||
name : "foo" | ||
}, | ||
arr1 : [ | ||
'a', 'b', 'c' | ||
], | ||
obj1 : { | ||
arr2 : [ | ||
'd', 'e', 'f' | ||
] | ||
}, | ||
created_at : 127817599, | ||
zero : 0 | ||
}; | ||
var path = require('path'); | ||
var exec = require('child_process').exec; | ||
var fs = require('fs'); | ||
var testCase = require('nodeunit').testCase; | ||
var ansidiff = require('ansidiff'); | ||
var warn = console.warn; | ||
function printTestName(testName) { | ||
console.log("\nRunning " + testName + ":"); | ||
console.log("-----------------------------------------"); | ||
} | ||
(function testSimpleSetup() { | ||
(function testProcessArgs() { | ||
printTestName("testProcessArgs"); | ||
//---- test cases | ||
var jsonC = new JSON.Command(); | ||
var conditions = [ "(name == 'foo')", "(text == 'boo')" ]; | ||
jsonC.processArgs([ "-c", conditions[0], "-c", conditions[1] ]); | ||
assert.equal(jsonC.conditionals[0], conditions[0], | ||
"conditionals contains specified conditional [0]"); | ||
assert.equal(jsonC.conditionals[1], conditions[1], | ||
"conditionals contains specified conditional [1]"); | ||
var data = { | ||
//setUp: function (callback) { | ||
// ... | ||
//}, | ||
})(); | ||
parseLookup: function (test) { | ||
var parseLookup = require('../lib/json.js').parseLookup; | ||
test.deepEqual(parseLookup('42'), [42]); | ||
test.deepEqual(parseLookup('a'), ['a']); | ||
test.deepEqual(parseLookup('a.b'), ['a', 'b']); | ||
test.deepEqual(parseLookup('a.b.c'), ['a', 'b', 'c']); | ||
(function testCreateRequestedKeys() { | ||
printTestName("testCreateRequestedKeys"); | ||
test.deepEqual(parseLookup('[42]'), [42]); | ||
test.deepEqual(parseLookup('["a"]'), ['a']); | ||
test.deepEqual(parseLookup('["a"]'), ['a']); | ||
var jsonC = new JSON.Command(); | ||
jsonC.processArgs([ "newKey" ]); | ||
jsonC.createRequestedKeys(testObj); | ||
test.deepEqual(parseLookup('b[42]'), ['b', 42]); | ||
test.deepEqual(parseLookup('b["a"]'), ['b', 'a']); | ||
test.deepEqual(parseLookup('b["a"]'), ['b', 'a']); | ||
assert.equal(testObj.newKey, null, | ||
"createRequestedKeys adds requested key to object"); | ||
test.deepEqual(parseLookup('[42].b'), [42, 'b']); | ||
test.deepEqual(parseLookup('["a"].b'), ['a', 'b']); | ||
test.deepEqual(parseLookup('["a"].b'), ['a', 'b']); | ||
jsonC = new JSON.Command(); | ||
jsonC.processArgs([ "zero" ]); | ||
jsonC.createRequestedKeys(testObj); | ||
test.deepEqual(parseLookup('["a-b"]'), ['a-b']); | ||
test.deepEqual(parseLookup('["a-b"]'), ['a-b']); | ||
test.deepEqual(parseLookup('["a.b"]'), ['a.b']); | ||
test.deepEqual(parseLookup('["a.b"]'), ['a.b']); | ||
test.deepEqual(parseLookup('["a[b"]'), ['a[b']); | ||
test.deepEqual(parseLookup('["a[b"]'), ['a[b']); | ||
test.deepEqual(parseLookup('["a]b"]'), ['a]b']); | ||
test.deepEqual(parseLookup('["a]b"]'), ['a]b']); | ||
assert.equal(testObj.zero, 0, | ||
"createRequestedKeys does not add null for 0 to object"); | ||
/* BEGIN JSSTYLED */ | ||
test.deepEqual(parseLookup("['a\\'[b']"), ["a'[b"]); | ||
test.deepEqual(parseLookup("['a\\'[b'].c"), ["a'[b", "c"]); | ||
/* END JSSTYLED */ | ||
delete testObj.newKey; | ||
})(); | ||
test.deepEqual(parseLookup('a/b', '/'), ['a', 'b']); | ||
test.deepEqual(parseLookup('a.b/c', '/'), ['a.b', 'c']); | ||
test.deepEqual(parseLookup('a.b/c[42]', '/'), ['a.b', 'c', 42]); | ||
test.deepEqual(parseLookup('["a/b"]', '/'), ['a/b']); | ||
(function testCheckConditionals() { | ||
printTestName("testCheckConditionals"); | ||
test.done(); | ||
} | ||
}; | ||
var jsonC = new JSON.Command(); | ||
jsonC.processArgs([ "-c", "(name == 'foo')"]); | ||
// Process includes and excludes from 'TEST_ONLY'. | ||
var only = [], | ||
excludes = []; | ||
if (process.env.TEST_ONLY) { | ||
warn('Note: Limiting "test.js" tests by $TEST_ONLY: "' + | ||
process.env.TEST_ONLY + '"'); | ||
var tokens = process.env.TEST_ONLY.trim().split(/\s+/); | ||
for (var i = 0; i < tokens.length; i++) { | ||
if (tokens[i][0] === '-') { | ||
excludes.push(tokens[i].slice(1)); | ||
} else { | ||
only.push(tokens[i]); | ||
} | ||
} | ||
} | ||
assert.equal(jsonC.checkConditionals(testObj), false, | ||
"checkConditionals (name=='foo') is false"); | ||
// Add a test case for each dir with a 'test.sh' script. | ||
var names = fs.readdirSync(__dirname); | ||
for (var i = 0; i < names.length; ++i) { | ||
var name = names[i]; | ||
if (only.length && only.indexOf(name) == -1) { | ||
continue; | ||
} | ||
if (excludes.length && excludes.indexOf(name) != -1) { | ||
continue; | ||
} | ||
var dir = path.join(__dirname, name); | ||
if (fs.statSync(dir).isDirectory()) { | ||
try { | ||
fs.statSync(path.join(dir, 'cmd')); | ||
} catch (e) { | ||
continue; | ||
} | ||
if (data[name] !== undefined) { | ||
throw ('error: test "' + name + '" already exists'); | ||
} | ||
data[name] = (function (dir) { | ||
return function (test) { | ||
var numTests = 0; | ||
jsonC = new JSON.Command(); | ||
jsonC.processArgs([ "-c", "(user.name == 'foo')"]); | ||
var expectedExitCode = null; | ||
try { | ||
var p = path.join(dir, 'expected.exitCode'); | ||
if (fs.statSync(p)) { | ||
expectedExitCode = Number(fs.readFileSync(p)); | ||
numTests += 1; | ||
} | ||
} catch (e) {} | ||
assert.equal(jsonC.checkConditionals(testObj), true, | ||
"checkConditionals (user.name=='foo') is true"); | ||
})(); | ||
var expectedStdout = null; | ||
try { | ||
var p = path.join(dir, 'expected.stdout'); | ||
if (fs.statSync(p)) { | ||
expectedStdout = fs.readFileSync(p, 'utf8'); | ||
numTests += 1; | ||
} | ||
} catch (e) {} | ||
(function testProcessKeyTransforms() { | ||
printTestName("testProcessKeyTransforms"); | ||
var expectedStderr = null; | ||
try { | ||
var p = path.join(dir, 'expected.stderr'); | ||
if (fs.statSync(p)) { | ||
expectedStderr = fs.readFileSync(p, 'utf8'); | ||
numTests += 1; | ||
} | ||
} catch (e) {} | ||
var tmpTestObj = { | ||
id : 19375093, text : "who knows", created_at : 127817599, | ||
user : { | ||
id : 1310571, name : "foo" | ||
} | ||
}; | ||
test.expect(numTests); | ||
exec('bash cmd', { | ||
'cwd': dir | ||
}, function (error, stdout, stderr) { | ||
var errmsg = ('\n-- return value:\n' + | ||
(error && error.code) + '\n-- expected stdout:\n' + | ||
expectedStdout + '\n-- stdout:\n' + stdout + | ||
'\n-- stdout diff:\n' + | ||
ansidiff.chars(expectedStdout, stdout)); | ||
if (expectedStderr !== null) { | ||
errmsg += '\n-- expected stderr:\n' + expectedStderr; | ||
} | ||
if (stderr !== null) { | ||
errmsg += '\n-- stderr:\n' + stderr; | ||
} | ||
if (expectedStderr !== null) { | ||
errmsg += '\n-- stderr diff:\n' + | ||
ansidiff.chars(expectedStderr, stderr); | ||
} | ||
var jsonC = new JSON.Command(); | ||
jsonC.processArgs([ "user.new_name=user.name", "-d"]); | ||
jsonC.createRequestedKeys(tmpTestObj); | ||
jsonC.processKeyTransforms(tmpTestObj); | ||
if (expectedExitCode !== null) { | ||
test.equal(expectedExitCode, error && error.code || 0, | ||
'\n\nunexpected exit code' + errmsg); | ||
} | ||
if (expectedStdout !== null) { | ||
test.equal(stdout, expectedStdout, | ||
'\n\nunexpected stdout' + errmsg); | ||
} | ||
if (expectedStderr !== null) { | ||
test.equal(stderr, expectedStderr, | ||
'\n\nunexpected stderr' + errmsg); | ||
} | ||
test.done(); | ||
}); | ||
} | ||
})(dir); | ||
} | ||
} | ||
assert.equal(tmpTestObj.user.new_name, testObj.user.name, | ||
"processKeyTransforms user.new_name = user.name is true"); | ||
})(); | ||
(function testProcessExecutables() { | ||
printTestName("testProcessExecutables"); | ||
var tmpTestObj = { | ||
id : 19375093, text : "who knows", created_at : 127817599, | ||
user : { | ||
id : 1310571, name : "foo" | ||
} | ||
}; | ||
var jsonC = new JSON.Command(); | ||
jsonC.processArgs([ "-e", "user.name = 'boo';"]); | ||
jsonC.processExecutables(tmpTestObj); | ||
assert.equal(tmpTestObj.user.name, "boo", | ||
"processExecutables user.name = 'boo' is true"); | ||
})(); | ||
(function testProcessKeys() { | ||
printTestName("testProcessKeys"); | ||
var jsonC = new JSON.Command(); | ||
jsonC.processArgs([ "user.name", "text", "arr1[1]", "obj1.arr2[2]" ]); | ||
assert.equal(jsonC.keys.length, 4, | ||
"processedKeys keys length == 4"); | ||
var resObj = jsonC.processKeys(testObj); | ||
assert.equal(resObj.user.name, testObj.user.name, | ||
"processKeys result object user.name = testObj.user.name is true"); | ||
assert.equal(resObj.text, testObj.text, | ||
"processKeys result object user.name = testObj.text is true"); | ||
assert.equal(resObj.id, undefined, | ||
"processKeys result object id is undefined is true"); | ||
assert.equal(resObj.created_at, undefined, | ||
"processKeys result object created_at is undefined is true"); | ||
assert.equal(resObj.user.id, undefined, | ||
"processKeys result object user.id is undefined is true"); | ||
assert.equal(resObj.arr1[0], testObj.arr1[1], | ||
"processKeys result object arr1[0] = testObj.arr1[0] is true"); | ||
assert.equal(resObj.obj1.arr2[0], testObj.obj1.arr2[2], | ||
"processKeys result object obj1.arr2[0] = testObj.obj1.arr2[2] is true"); | ||
})(); | ||
(function testDiffFriendly() { | ||
printTestName("testLeadingComma"); | ||
var jsonC = new JSON.Command(); | ||
jsonC.processArgs([ "-," ]); | ||
assert.equal(jsonC.stringify(testObj), | ||
'{ "id": 19375093\n, "text": "who knows"\n, "user":\n { "id": 1310571\n , "name": "foo"\n }\n, "arr1":\n [ "a"\n , "b"\n , "c"\n ]\n, "obj1":\n { "arr2":\n [ "d"\n , "e"\n , "f"\n ]\n }\n, "created_at": 127817599\n, "zero": 0\n}', | ||
"Leading-comma output selection works and formats test object correctly"); | ||
assert.equal(jsonC.stringify([[]]), "[ []\n]", | ||
"Leading-comma output nests arrays correctly"); | ||
assert.equal(jsonC.stringify({"":[{"deep":{"null":null}}]}), | ||
'{ "":\n [ { "deep":\n { "null": null\n }\n }\n ]\n}', | ||
"Leading-comma output nests deep object/array combinations correctly"); | ||
})(); | ||
})(); | ||
console.log("\nAll tests passed!\n"); | ||
exports['test'] = testCase(data); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
203274
148
1874
1
6
6
120
6