1. json(1)
  2. json(1)

NAME

json - JSON love for your command line. A.k.a. "jsontool".

SYNOPSIS

something-generating-JSON-on-stdout | json [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.

Auto-arrayification

Adjacent objects or arrays separated by no space or by a newline are "arrayified". This can be helpful for, e.g.:

$ cat *.json | json ...

and similar.

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

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

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

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

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.

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 then stripped you can use:

-H
drop any HTTP header block (as from curl -i ...)

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.

-d DELIM

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

-A

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.

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

-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

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

-i

Shortcut for -o inspect.

-j

Shortcut for -o json.

EXAMPLES

Let's use the Github API to look at the node project:

$ curl -s http://github.com/api/v2/json/repos/show/joyent/node
{"repository":{"organization":"joyent","watchers":15172,...

Nice output by default:

$ curl -s http://github.com/api/v2/json/repos/show/joyent/node | json
{
  "repository": {
    "organization": "joyent",
    "watchers": 15172,
    "has_downloads": false,
    "url": "https://github.com/joyent/node",
    "homepage": "http://nodejs.org/",
    "fork": false,
    "has_issues": true,
    "has_wiki": true,
    "forks": 1835,
    "size": 28000,
    "private": false,
    "name": "node",
    "owner": "joyent",
    "open_issues": 443,
    "description": "evented I/O for v8 javascript",
    "language": "JavaScript",
    "created_at": "2009/05/27 09:29:46 -0700",
    "pushed_at": "2012/05/24 09:55:29 -0700"
  }
}

Say you just want to extract one value:

$ curl -s https://github.com/api/v2/json/repos/show/joyent/node \
  | json repository.open_issues
443

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://github.com/api/v2/json/repos/show/joyent/node \
  | json repository
HTTP/1.1 200 OK
Server: nginx/1.0.13
Date: Thu, 24 May 2012 17:25:59 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Status: 200 OK
X-RateLimit-Limit: 60
ETag: "7e9ae0fd892a197256419a180af28f79"
X-Frame-Options: deny
X-RateLimit-Remaining: 58
X-Runtime: 14
Content-Length: 439
Cache-Control: private, max-age=0, must-revalidate

{
  "organization": "joyent",
  "watchers": 15172,
  "has_downloads": false,
  "url": "https://github.com/joyent/node",
  "homepage": "http://nodejs.org/",
  "fork": false,
  "has_issues": true,
  "has_wiki": true,
  "forks": 1835,
  "size": 28000,
  "private": false,
  "name": "node",
  "owner": "joyent",
  "open_issues": 443,
  "description": "evented I/O for v8 javascript",
  "language": "JavaScript",
  "created_at": "2009/05/27 09:29:46 -0700",
  "pushed_at": "2012/05/24 09:55:29 -0700"
}

Or, say you are stuck with the headers in your pipeline, 'json -H' will drop HTTP headers:

$ curl -is https://github.com/api/v2/json/repos/show/joyent/node \
  | json -H repository.watchers
15172

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 http://github.com/api/v2/json/repos/search/nodejs \
  | json 'repositories[2].description'
Connect is a middleware layer for Node.js

Having the quote to avoid shell interpretation of '[' is annoying, so json allows a special case for an integer lookup:

$ curl -s http://github.com/api/v2/json/repos/search/nodejs \
  | json 'repositories.2.description'
Connect is a middleware layer for Node.js

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. Continuing our example above, let's first get a list of repositories for a "nodejs" search on github:

$ curl -s http://github.com/api/v2/json/repos/search/nodejs | json repositories
[
  {
    "type": "repo",
    "followers": 3922,
    "watchers": 3922,
    "has_issues": true,
    "description": "Sinatra inspired web development framework ...",
    "url": "https://github.com/visionmedia/express",
    "has_downloads": true,
    "created_at": "2009/06/26 11:56:01 -0700",
    "pushed": "2011/09/28 10:27:26 -0700",
    "forks": 345,
...

We can then print a table with just some fields as follows:

$ curl -s http://github.com/api/v2/json/repos/search/nodejs \
    | json repositories | json -a forks url
345 https://github.com/visionmedia/express
136 https://github.com/unconed/TermKit
292 https://github.com/LearnBoost/socket.io

Ultimately this can be useful for then using other command-line tools. For example, we could get the list of top-five most forked "nodejs" github repos:

$ curl -s http://github.com/api/v2/json/repos/search/nodejs \
    | json repositories | json -a forks url | sort -n | tail -5
269 https://github.com/visionmedia/jade
298 https://github.com/senchalabs/connect
539 https://github.com/blueimp/jQuery-File-Upload
552 https://github.com/LearnBoost/socket.io
634 https://github.com/visionmedia/express

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 http://github.com/api/v2/json/repos/search/nodejs \
    | json repositories | json -a forks url -d,

$ curl -s http://github.com/api/v2/json/repos/search/nodejs \
    | json repositories | json -a forks watchers url -d,
345,3922,https://github.com/visionmedia/express
136,3128,https://github.com/unconed/TermKit
292,2777,https://github.com/LearnBoost/socket.io
104,1640,https://github.com/mishoo/UglifyJS
...

Auto-arrayification

Adjacent objects or arrays are 'arrayified'. 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
[
  {
    "a": 1
  },
  {
    "b": 2
  }
]
$ echo '[1,2][3,4]' | json
[
  1,
  2,
  3,
  4
]

This can be useful when processing a number of JSON files, e.g.:

$ cat my_data/*.json | json ...

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 \
    http://github.com/api/v2/json/issues/search/joyent/node/open/{} \
    | json -a issues | json -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 -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
[{"name":"Trent"},{"name":"Ewan"}]

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' } ]

Validating JSON

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

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}

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:

$ 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 element separately (use -A to override this):

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

PROJECT & BUGS

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

LICENSE

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

json is Copyright (c) 2012 Trent Mick

  1. May 2012
  2. json(1)