JSON(1)json tool manual JSON(1)NAMEjson - (aka "jsontool") JSON love for your command line.
SYNOPSIS
something-generating-JSON-on-stdout | json [OPTIONS] [LOOKUPS]
json-f FILE [OPTIONS] [LOOKUPS...]
DESCRIPTION
Pipe in your JSON for pretty-printing, JSON validation, filtering, and
modification. Supply one or more LOOKUPS to extract a subset of the
JSON. HTTP header blocks are skipped by default.
Grouping
(Added in json v4.) Use ´-g´ or ´--group´ to group objects (into an
array of objects) or concatenate arrays (into a single array) separated
by no space or by a newline. This can be helpful for, e.g.:
$ cat *.json | json-g ...
and similar.
In json v3 and earlier, this used to be called "auto-arrayification"
and was implicit. See the COMPATIBILITY section below.
Merging
(Added in json v4.) Use ´--merge´ or ´--deep-merge´ to merge adjacent
JSON objects in the input. Keys in the last object win.
$ echo ´{"one":"un","two":"deux"}
{"one":"uno","three":"tres"}´ | json--merge
{
"one": "uno",
"two": "deux",
"three": "tres"
}
This could be useful for merging multiple config files, e.g.:
$ cat /opt/app/etc/defaults.json \
/etc/app/config.json \
~/.app/config.json | json--merge
Execution
Use the -e CODE option to execute code on the input JSON.
$ echo ´{"name":"trent","age":38}´ | json-e ´age++´
{
"name": "trent",
"age": 39
}
If input is an array, this will automatically process each item sepa‐
rately.
Conditional filtering
Use the -c CODE option to filter the input JSON.
$ echo ´[{"age":38},{"age":4}]´ | json-c ´age>21´
[{"age":38}]
If input is an array, this will automatically process each item sepa‐
rately.
Lookups
Use lookup arguments to extract particular values:
$ echo ´{"name":"trent","age":38}´ | json name
trent
Use -a for array processing of lookups and tabular output:
$ echo ´{"name":"trent","age":38}´ | json name
trent
$ echo ´[{"name":"trent","age":38},
{"name":"ewan","age":4}]´ | json-a name age
trent 38
ewan 4
Integral values work for array index lookups:
$ echo ´["a", "b", "c"]´ | json 1
b
Negative array indeces are also supported:
$ echo ´["a", "b", "c"]´ | json-1
c
$ echo ´["a", "b", "c"]´ | json-2
b
Pretty-printing
Output is "jsony" by default: 2-space indented JSON with one exception,
a single string value is printed without quotes.
$ echo ´{"name": "trent", "age": 38}´ | json
{
"name": "trent",
"age": 38
}
Use -ojson for explicit JSON, -o json-N for N-space indent:
$ echo ´{"name": "trent", "age": 38}´ | json-o json-0
{"name":"trent","age":38}
Use -H to exclude a leading HTTP header block as from curl -i.
Listing keys
Sometimes you want the list of keys for an object. Use -k or --keys for
that:
$ echo ´{"name": "trent", "age": 38}´ | json-k
[
"name",
"age"
]
$ echo ´{"name": "trent", "age": 38}´ | json-ka
name
age
OPTIONS-h, --help
Print this help info and exit.
--version
Print version of this command and exit.
-q, --quiet
Don´t warn if input isn´t valid JSON.
By default json will process input from stdin. Alternative, an input
file (or files) can be specified:
-f FILE
Specify an input file (instead of stdin).
If your JSON output is a REST API response, it might include the head‐
ers (e.g. when calling with curl -i). By default json will pass those
headers through (without choking on them). However if you want them
stripped you can use:
-H drop any HTTP header block (as from curl -i ...)
Other pre-JSON input handling:
-g, --group
Group adjacent objects into an array of objects, or concatenate
adjacent arrays into a single array.
--merge, --deep-merge
Merge adjacent objects into a single object with merged keys.
Values in later objects win. Use --deep-merge to recursively
merge keys in objects.
You can process elements of an input array separately and generate tab‐
ular output:
-a, --array
Process input as an array of separate inputs and output in tabu‐
lar form.
-d DELIM
Delimiter character for tabular output (default is ´ ´).
-A Process input as a single object, i.e. stop -e and -c automati‐
cally processing each item of an input array.
You can execute code on (-e) and filter (-c) the input (this is done
before LOOKUPS are processed, if any). If datum is an object, then a
shortcut is <key>. To remove a key, use this.<key> = undefined. For
array items, use this[<index>] = 42.
-e CODE
Execute the given code on the input. If input is an array, then
each item of the array is processed separately (use -A to over‐
ride).
-c CODE
Filter the input with CODE. If CODE returns false-y, then the
item is filtered out. If input is an array, then each item of
the array is processed separately (use -A to override).
Finally, if LOOKUP arguments are given, these are extracted from the
JSON. By default . is used as a separator for nested object lookup.
This can be overridden:
-D DELIM
Delimiter char between LOOKUPS (default is ´.´). For example: $
echo ´{"a.b": {"b": 1}}´ | json-D / a.b/b
An alternative to lookups is to output the keys of the input object:
-k, --keys
Output the input object´s keys.
json can be restricting to just validating its input, i.e. processing
and output of the input is skipped:
--validate
Just validate the input, no processing or output of the JSON
content.
By default json outputs in "jsony" mode. Basically this is JSON output,
with the exception that a single string output value is emitted without
the quotes. The intention here is to be of most use to the UNIX com‐
mand-line. Other output formats are supported:
-o MODE, --output MODE
Specify an output mode. One of jsony (the default; JSON, if a
single string then quotes are elided), json (JSON output,
2-space indent), json-N (JSON output, N-space indent, e.g.
´json-4´), or inspect (node.js util.inspect output).
-i Shortcut for -o inspect.
-j Shortcut for -o json.
EXAMPLES
A typical JSON REST API response:
$ curl -s http://ifconfig.me/all.json
{"connection":"","ip_addr":"216.57.203.67","lang":"","remote_host":...
Nice output by default:
$ curl -s http://ifconfig.me/all.json | json
{
"connection": "",
"ip_addr": "201.73.103.12",
"lang": "",
"remote_host": "",
"user_agent": "curl/7.23.1 (i386-sun-solaris2.11) libcurl/7.23.1 OpenSSL/0.9.8w zlib/1.2.3 libidn/1.23 libssh2/1.2.2",
"charset": "",
"port": "63713",
"via": "",
"forwarded": "",
"mime": "*/*",
"keep_alive": "",
"encoding": ""
}
Say you just want to extract one value:
$ curl -s http://ifconfig.me/all.json | json ip_addr
201.73.103.12
Or, looking at the node.js project https://github.com/joyent/node using
the Github API:
$ curl -s https://api.github.com/repos/joyent/node | json open_issues
517
If you use curl -i to get HTTP headers (because perhaps they contain
relevant information), json will skip the HTTP headers automatically:
$ curl -is https://api.github.com/repos/joyent/node | json
HTTP/1.1 200 OK
Server: nginx/1.0.13
Date: Tue, 24 Jul 2012 04:01:08 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Status: 200 OK
ETag: "1a21d980a01768dde42145ce2b58694c"
X-RateLimit-Remaining: 4997
Content-Length: 1513
Cache-Control: public, max-age=60
Vary: Accept
X-RateLimit-Limit: 5000
Last-Modified: Tue, 24 Jul 2012 03:50:11 GMT
{
"master_branch": "master",
"has_issues": true,
"has_downloads": false,
"homepage": "http://nodejs.org/",
"html_url": "https://github.com/joyent/node",
Or, say you are stuck with the headers in your pipeline, ´json -H´ will
drop HTTP headers:
$ curl -is https://api.github.com/repos/joyent/node | json-H forks
2158
Here is an example that shows indexing a list. (The given "lookup"
argument is basically JavaScript code appended, with ´.´ if necessary,
to the JSON data and eval´d.)
$ curl -s https://api.github.com/legacy/repos/search/nodejs \
| json ´repositories[2].name´
socket.io
Having the quote to avoid shell interpretation of ´[´ is annoying, so
json allows a special case for an integer lookup:
$ curl -s https://api.github.com/legacy/repos/search/nodejs \
| json ´repositories.2.name´
socket.io
Array processing with -a
json includes the -a (aka --array) option for processing each element
of an input JSON array independently and using tabular output. Let´s
first get a list of open node.js issues (note that this is a subset
because of GH API pagination http://developer.github.com/v3/#pagina‐
tion):
$ curl -s https://api.github.com/repos/joyent/node/issues?state=open\&per_page=100
[
{
"number": 3757,
"html_url": "https://github.com/joyent/node/issues/3757",
"body": "Fix #3756.\n\nReview, please: @TooTallNate",
"milestone": null,
"user": {
"gravatar_id": "73a2b24daecb976af81e010b7a3ce3c6",
"login": "isaacs",
"avatar_url": "https://secure.gravatar.com/avatar/73a2b24dae...
We can then print a table with just some fields as follows:
$ curl -s https://api.github.com/repos/joyent/node/issues?state=open\&per_page=100 \
| json-a comments number title
0 3757 readline: Remove event listeners on close
0 3756 readline: No way to completely unhook interface from input/output
1 3755 node-v0.6.20 hello example segfaults on RaspberryPi (w/Arch + bash)
0 3753 Prohibit same listeners in EventEmitter. Closes #964.
1 3752 Auto-detect hardfloat eabi and armv7 variables on ARM based on compiler
3 3751 persistent REPL history
0 3749 glibc errors on SheevaPlug / Debian Squeeze
Ultimately this can be useful for then using other command-line tools.
For example, we could get the list of top-five most commented open node
issues:
$ curl -s https://api.github.com/repos/joyent/node/issues?state=open\&per_page=100 \
| json-a comments number title | sort -n | tail -5
9 3510 Automatically `.toString()` functions in REPL.
11 3668 JSON documentation index listing
12 3624 Add a return value to Buffer.write* methods that returns the ...
12 3655 defer dgram listening event
14 3613 Connections closed by node stay permanently in FIN_WAIT2
Or get a breakdown by ISO language code of the recent tweets mentioning
"nodejs":
$ curl -s http://search.twitter.com/search.json?q=nodejs\&rpp=100 \
| json results | json-a iso_language_code | sort | uniq -c | sort
1 es
1 no
1 th
4 ru
12 ja
23 pt
58 en
The -d option can be used to specify a delimiter:
$ curl -s https://api.github.com/repos/joyent/node/issues?state=open \
| json-a created_at number title -d,
2012-07-24T03:45:03Z,3757,readline: Remove event listeners on close
2012-07-24T03:32:10Z,3756,readline: No way to completely unhook inte...
2012-07-23T21:17:50Z,3755,node-v0.6.20 hello example segfaults on Ra...
2012-07-22T16:17:49Z,3753,Prohibit same listeners in EventEmitter. C...
2012-07-22T13:43:40Z,3752,Auto-detect hardfloat eabi and armv7 varia...
Grouping
You can use the ´-g´ or ´--group´ option to group adjacent objects into
an array of those objects; or to concatenate adjacent arrays into a
single array. To attempt to avoid false positives inside JSON strings,
adjacent elements must have either no whitespace separation or at least
a newline separation. Examples:
$ echo ´{"a":1}{"b":2}´ | json-g # group into array of objects
[
{
"a": 1
},
{
"b": 2
}
]
$ echo ´[1,2][3,4]´ | json-g # concantenate into one array
[
1,
2,
3,
4
]
This can be useful when processing a number of JSON files, e.g.:
$ cat my_data/*.json | json-g ...
Or when composing multiple JSON API response, e.g. this somewhat con‐
trived search for node.js bugs mentioning "tty" or "windows":
$ echo tty windows | xargs -n1 -I{} curl -s \
https://api.github.com/legacy/issues/search/joyent/node/open/{} \
| json-g -a issues | json-g -a number title
623 Non-userfacing native modules should be prefixed with _
861 child_process fails after stdin close
1157 `child_process` module should read / write password prompts
1180 Ctrl+Shift+BS can´t be input.
Output formatting
You can use the ´-o MODE´ option (or ´--output MODE´) to control the
output flavour. By default the output is "jsony" (JSON, except that a
simple string is printed without the quotes):
$ echo ´[{"name": "Trent"},{"name": "Ewan"}]´ | json
[
{
"name": "Trent"
},
{
"name": "Ewan"
}
]
$ echo ´[{"name": "Trent"},{"name": "Ewan"}]´ | json ´0.name´
Trent
$ echo ´[{"name": "Trent"},{"name": "Ewan"}]´ | json ´0.name´ -o jsony
Trent
Or for strict JSON output:
$ echo ´[{"name": "Trent"},{"name": "Ewan"}]´ | json-ojson
[
{
"name": "Trent"
},
{
"name": "Ewan"
}
]
By default this uses a 2-space indent. That can be changed with a "-N"
suffix:
$ echo ´[{"name": "Trent"},{"name": "Ewan"}]´ | json-o json-4
[
{
"name": "Trent"
},
{
"name": "Ewan"
}
]
$ echo ´[{"name": "Trent"},{"name": "Ewan"}]´ | json-o json-0
[{"name":"Trent"},{"name":"Ewan"}]
You can get colored (non-JSON) output using node.js´s util.inspect
http://nodejs.org/docs/latest/api/all.html#util.inspect:
$ echo ´[{"name": "Trent"},{"name": "Ewan"}]´ | json-o inspect
[ { name: ´Trent´ },
{ name: ´Ewan´ } ]
Validation
Since v1.2.0 json will give position information and context for JSON
syntax errors (SyntaxError). This can be handy for validating data and
config files:
$ cat config.json | json
json: error: input is not JSON: Unexpected ´,´ at line 17, column 5:
, { "name": "smartos64-1.4.7"
....^
{
"use-proxy": false
$ echo $?
1
Processing and output of the input JSON can be suppressed with the
--validate option:
$ cat config.json | json--validate
json: error: input is not JSON: Unexpected ´,´ at line 17, column 5:
, { "name": "smartos64-1.4.7"
....^
Together with the -q you can get silent, exit-status-only, JSON valida‐
tion:
$ cat config.json | json--validate -q
$ echo $?
1
Executing code snippets on input
You can use the -e CODE option to execute small code snippets to mas‐
sage 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}
If the input is an array, then -e will automatically process each ele‐
ment separately (use -A to override this):
$ echo ´[{"name":"trent", "age":38}, {"name":"ewan", "age":4}]´ \
| json-e ´age++´
[
{
"name": "trent",
"age": 39
},
{
"name": "ewan",
"age": 5
}
]
Filtering with ´-c´
You can use the -c CODE option to filter the input:
$ echo ´{"name":"trent", "age":38}´ | json-c ´age>21´
{
"name": "trent",
"age": 38
}
$ echo ´{"name":"trent", "age":38}´ | json-c ´age==16´
$
If the input is an array, then -c will automatically process each ele‐
ment separately (use -A to override this):
$ echo ´[{"name":"trent", "age":38}, {"name":"ewan", "age":4}]´ \
| json-c ´age>21´
[
{
"name": "trent",
"age": 38
}
]
COMPATIBILITY
This is json version 4. The major version is incremented when there is
a backward incompatible change.
· v4: Made "auto-arrayification" require an explicit ´-g´ or
´--group´ option to prefer that implicit processing never magically
fix otherwise invalid JSON. The feature is now called grouping.
· v3: Cleaned up json and "jsony" output formatting to be more con‐
sistent, especially for array processing.
See the changelog https://github.com/trentm/json/blob/master/CHANGES.md
for full compatibility and change details.
PROJECT & BUGSjson is written in JavaScript and requires node.js (node). The project
lives at https://github.com/trentm/json and is published to npm as
"jsontool" ("json" was already taken, boo).
· README, Install notes: https://github.com/trentm/json#readme
· Report bugs to https://github.com/trentm/json/issues.
· See the full changelog at: https://github.com/trentm/json/blob/mas‐
ter/CHANGES.md
LICENSE
MIT License (see https://github.com/trentm/json/blob/mas‐
ter/LICENSE.txt)
COPYRIGHTjson is Copyright (c) 2012 Trent Mick
July 2012 JSON(1)