1. json(1)
  2. json tool manual
  3. json(1)


json - (aka "jsontool") JSON love for your command line.


something-generating-JSON-on-stdout | json [OPTIONS] [LOOKUPS]



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.


(Added in json v4.) Use '-g' or '--group' to group adjacent objects into a single JSON array or to concatenate adjacent arrays into a single array. E.g.:

$ echo '{"a":1}
{"b": 2}' | json -g
    "a": 1
    "b": 2

$ echo '["one"]
["two"]' | json -g

"Adjacent" objects means objects separated by a newline, or by no space at all. Adjacent arrays means separate by a newline. These conditions are chosen as a balance between (a) not being ambiguous to parse with a simple regex and (b) enough to be useful for common cases.

Grouping can be helpful for "one JSON object per line" formats (like Bunyan) or for things such as:

$ cat *.json | json -g ...

As of json v5.1, json -ga will stream, e.g.:

$ yes '{"foo":"bar"}' | json -ga

In json v3 and earlier, this used to be called "auto-arrayification" and was implicit. In json v4 and v5 grouping of adjacent arrays separate by no space was allowed. That was dropped in v6 (see issue #55. See the COMPATIBILITY section below.


(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


Use the -e CODE option to execute (JavaScript) code on the input JSON.

$ echo '{"name":"trent","age":38}' | json -e 'this.age++'
  "name": "trent",
  "age": 39

If input is an array, this will automatically process each item separately.

Conditional filtering

Use the -c CODE option to run JavaScript code ending with a statement returning a boolean to filter the input JSON.

$ echo '[{"age":38},{"age":4}]' | json -c 'this.age > 21'

If input is an array, this will automatically process each item separately.


Use lookup arguments to extract particular values:

$ echo '{"name":"trent","age":38}' | json name

Use -a for array processing of lookups and tabular output:

$ echo '{"name":"trent","age":38}' | json name
$ 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

Negative array indices are also supported:

$ echo '["a", "b", "c"]' | json -- -1
$ echo '["a", "b", "c"]' | json -- -2

If your lookup isn't a number or a JS indentifier you can always use JavaScript array-style lookups like this:

$ echo '{"http://example.com": "my-value"} | json '["http://example.com"]'

just like you would in JavaScript:

$ node
> var d = '{"http://example.com": "my-value"}
> d["http://example.com"]


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 -o json for explicit JSON, -o json-N for N-space indent:

$ echo '{"name": "trent", "age": 38}' | json -o json-0

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
$ echo '{"name": "trent", "age": 38}' | json -ka


-h, --help

Print this help info and exit.


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. Alternatively, an input file (or files) can be specified:

Specify an input file (instead of stdin).

By default json output is to stdout. Together with -f FILE, in-place editing can be done:

-I, --in-place
Edit the file given with -f FILE in-place. Lookups are not allowed with in-place editing, because it is too easy to accidentally lose file data.

If your JSON output is a REST API response, it might include the headers (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:

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 tabular output:

-a, --array

Process input as an array of separate inputs and output in tabular form.


Delimiter character for tabular output (default is ' ').


Process input as a single object, i.e. stop -e and -c automatically 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.


Execute the given JavaScript code on the input. If input is an array, then each item of the array is processed separately (use -A to override).


Filter the input with JavaScript 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:

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:

-n, --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 command-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).


Shortcut for -o inspect.


Shortcut for -o json.


A typical JSON REST API response:

$ curl -s http://ifconfig.me/all.json

Nice output by default:

$ curl -s http://ifconfig.me/all.json | json
  "connection": "",
  "ip_addr": "",
  "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

Or, looking at the node.js project using the Github API:

$ curl -s https://api.github.com/repos/joyent/node | json open_issues

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

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'

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'

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):

$ 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...


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

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 contrived 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'

$ echo '[{"name": "Trent"},{"name": "Ewan"}]' | json '0.name' -o jsony

Or for strict JSON output:

$ echo '[{"name": "Trent"},{"name": "Ewan"}]' | json -o json
    "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

You can get colored (non-JSON) output using node.js's util.inspect:

$ echo '[{"name": "Trent"},{"name": "Ewan"}]' | json -o inspect
[ { name: 'Trent' },
  { name: 'Ewan' } ]


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 $?

Processing and output of the input JSON can be suppressed with the -n, --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 validation:

$ cat config.json | json -nq
$ echo $?

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"'

Or omit the this. as a shortcut:

$ echo '{"foo": "bar"}' | json -e 'foo="baz"'
$ echo '{"age": 38}' | json -e 'age++'

Set a key to undefined to remove it:

$ echo '{"one": 1, "two": 2}' | json -e 'this.one=undefined'

If the input is an array, then -e will automatically process each element 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 (this is JavaScript code):

$ echo '{"name":"trent", "age":38}' | json -c 'this.age > 21'
  "name": "trent",
  "age": 38
$ echo '{"name":"trent", "age":38}' | json -c 'this.age==16'

If the input is an array, then -c will automatically process each element separately (use -A to override this):

$ echo '[{"name":"trent", "age":38}, {"name":"ewan", "age":4}]' \
    | json -c 'this.age>21'
    "name": "trent",
    "age": 38

In-place editing

You can edit a file in place with -I and -f FILE:

$ cat config.json

$ json -I -f config.json                   # format the file
json: updated "config.json" in-place
$ cat config.json
  "hostname": ""

$ json -I -f config.json -e 'this.port=8080'  # add bar field
json: updated "config.json" in-place
$ cat config.json
  "hostname": "",
  "port": 8080

Some limitations. Only one file at a time:

$ json -I -f foo.json -f bar.json
json: error: must specify exactly one file with '-f FILE' to use -I/--in-place

Lookups are not allowed:

$ json -I -f foo.json key.subkey
json: error: lookups cannot be specified with in-place editing (-I/--in-place), too easy to lose content

because that can too easily result in data loss, e.g. with something like:

$ json -I -f *.json    # if there is more than match to the glob
json: error: lookups cannot be specified with in-place editing (-I/--in-place), too easy to lose content


The json tool major version is incremented when there is a backward incompatible change. An overview of those changes is here.

See the changelog for full compatibility and change details.


json 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).


MIT License (see https://github.com/trentm/json/blob/master/LICENSE.txt)

json is Copyright (c) 2012 Trent Mick

  1. June 2013
  2. json(1)
Fork me on GitHub