AnC
AnC

Reputation:

How can I pretty-print JSON in a shell script?

Is there a (Unix) shell script to format JSON in human-readable form?

Basically, I want it to transform the following:

{ "foo": "lorem", "bar": "ipsum" }

... into something like this:

{
    "foo": "lorem",
    "bar": "ipsum"
}

Upvotes: 3711

Views: 1872041

Answers (30)

jassinm
jassinm

Reputation: 7491

I usually just do:

echo '{"test":1,"test2":2}' | python -mjson.tool

And to retrieve select data (in this case, "test"'s value):

echo '{"test":1,"test2":2}' | python -c 'import sys,json;data=json.loads(sys.stdin.read()); print data["test"]'

If the JSON data is in a file:

python -m json.tool filename.json

If you want to do it all in one go with curl on the command line using an authentication token:

curl -X GET -H "Authorization: Token wef4fwef54te4t5teerdfgghrtgdg53" http://testsite/api/ | python -mjson.tool

Upvotes: 193

peak
peak

Reputation: 116640

jj (https://github.com/tidwall/jj) is super-fast, can handle ginormous JSON documents economically, does not mess with valid JSON numbers, and is easy to use, e.g.

jj -p # for reading from STDIN

or

jj -p -i input.json

It is (2018) still quite new so maybe it won’t handle invalid JSON the way you expect, but it is easy to install on major platforms.

Upvotes: 21

Vita Pluvia
Vita Pluvia

Reputation: 470

You can use: jq

It's very simple to use and it works great! It can handle very large JSON structures, including streams. You can find their tutorials here.

Usage examples:

$ jq --color-output . file1.json file1.json | less -R

$ command_with_json_output | jq .

$ jq # stdin/"interactive" mode, just enter some JSON

$ jq <<< '{ "foo": "lorem", "bar": "ipsum" }'
{
  "bar": "ipsum",
  "foo": "lorem"
}

Or use jq with identity filter:

$ jq '.foo' <<< '{ "foo": "lorem", "bar": "ipsum" }'
"lorem"

Upvotes: 1614

Roberto
Roberto

Reputation: 1

I know that the original post asked for a shell script, but there are so many useful and irrelevant answers that probably did not help the original author. Adding on to irrelevance :)

BTW I could not get any command line tools to work.

If somebody want simple JSON JavaScript code, they could do:

JSON.stringfy(JSON.parse(str), null, 4)

http://www.geospaces.org/geoweb/Wiki.jsp?page=JSON%20Utilities%20Demos

Here is JavaScript code that not only pretties the JSON, but orders them by their attribute or by attribute and level.

If input is

{ "c": 1, "a": {"b1": 2, "a1":1 }, "b": 1},

it either prints (groups all the objects together):

{
     "b": 1,
     "c": 1,
     "a": {
          "a1": 1,
          "b1": 2
     }
}

OR (just orders by key):

{
 "a": {
      "a1": 1,
      "b1": 2
 },
 "b": 1,
 "c": 1
}

Upvotes: -4

user3132194
user3132194

Reputation: 2547

Found 4 already available tools in my Gentoo system:

From package dev-libs/json-glib 19K ELF

json-glib-format -p file.json

From package dev-lang/perl 4,9K Perl script

(keeps unicode symbols as-is)

cat file.json | json_pp

From package dev-libs/yajl 43K ELF

cat file.json | json_reformat

From package dev-lang/python

(escapes unicode symbols to unreadable \u hex notation, had to replace python with python3 on debian system)

python -m json.tool file.json

Upvotes: 0

Reino
Reino

Reputation: 3423

You can use .

Xidel is a command line tool to download and extract data from HTML/XML pages or JSON-APIs, using CSS, XPath 3.0, XQuery 3.0, JSONiq or pattern templates. It can also create new or transformed XML/HTML/JSON documents.

Xidel pretty-prints by default:

$ xidel -se '$json' <<< '{"foo":"lorem","bar":"ipsum"}'
{
  "foo": "lorem",
  "bar": "ipsum"
}

or:

$ echo '{"foo":"lorem","bar":"ipsum"}' | xidel -se '$json'
{
  "foo": "lorem",
  "bar": "ipsum"
}

Upvotes: 1

Orest Ivasiv
Orest Ivasiv

Reputation: 181

Here is a Groovy one-liner:

echo '{"foo": "lorem", "bar": "ipsum"}' | groovy -e 'import groovy.json.*; println JsonOutput.prettyPrint(System.in.text)'

Upvotes: 3

lev
lev

Reputation: 2977

gem install jsonpretty
echo '{"foo": "lorem", "bar": "ipsum"}' | jsonpretty

This method also "Detects HTTP response/headers, prints them untouched, and skips to the body (for use with `curl -i')".

Upvotes: 4

numan salati
numan salati

Reputation: 19494

Here is how to do it with Groovy script.

Create a Groovy script, let's say "pretty-print"

#!/usr/bin/env groovy

import groovy.json.JsonOutput

System.in.withReader { println JsonOutput.prettyPrint(it.readLine()) }

Make script executable:

chmod +x pretty-print

Now from the command line,

echo '{"foo": "lorem", "bar": "ipsum"}' | ./pretty-print

Upvotes: 4

Bryan Larsen
Bryan Larsen

Reputation: 10006

$ sudo apt-get install edit-json
$ prettify_json myfile.json

Upvotes: 5

josch
josch

Reputation: 7134

The tool ydump is a JSON pretty-printer:

$ ydump my_data.json
{
  "foo": "lorem",
  "bar": "ipsum"
}

Or you can pipe in the JSON:

$ echo '{"foo": "lorem", "bar": "ipsum"}' | ydump
{
  "foo": "lorem",
  "bar": "ipsum"
}

This is probably the shortest solution apart from using the jq tool.

This tool is part of the yojson library for OCaml, and is documented here.

On Debian and derivatives, the package libyojson-ocaml-dev contains this tool. Alternatively, yojson can be installed via OPAM.

Upvotes: 6

adius
adius

Reputation: 14952

For Node.js you can also use the "util" module. It uses syntax-highlighting, smart indentation, removes quotes from keys and just makes the output as pretty as it gets.

cat file.json | node -e "process.stdin.pipe(new require('stream').Writable({write: chunk =>  {console.log(require('util').inspect(JSON.parse(chunk), {depth: null, colors: true}))}}))"

Upvotes: 7

pimlottc
pimlottc

Reputation: 3126

J.F. Sebastian's solutions didn't work for me in Ubuntu 8.04.
Here is a modified Perl version that works with the older 1.X JSON library:

perl -0007 -MJSON -ne 'print objToJson(jsonToObj($_, {allow_nonref=>1}), {pretty=>1}), "\n";'

Upvotes: 8

slashmili
slashmili

Reputation: 1220

I'm using httpie

$ pip install httpie

And you can use it like this

$ http PUT localhost:8001/api/v1/ports/my 
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 93
Content-Type: application/json
Date: Fri, 06 Mar 2015 02:46:41 GMT
Server: nginx/1.4.6 (Ubuntu)
X-Powered-By: HHVM/3.5.1
      
{
    "data": [], 
    "message": "Failed to manage ports in 'my'. Request body is empty", 
    "success": false
}

Upvotes: 8

svidgen
svidgen

Reputation: 14282

The PHP version, if you have PHP >= 5.4.

alias prettify_json=php -E '$o = json_decode($argn); print json_encode($o, JSON_PRETTY_PRINT);'
echo '{"a":1,"b":2}' | prettify_json

Upvotes: 9

Pablo Fernandez heelhook
Pablo Fernandez heelhook

Reputation: 12503

Here is a Ruby solution that is better than Json's prettify command. The gem colorful_json is fairly good.

gem install colorful_json
echo '{"foo": "lorem", "bar": "ipsum"}' | cjson
{
  "foo": "lorem",
  "bar": "ipsum"
}

Upvotes: 10

harish2704
harish2704

Reputation: 591

A one-line solution using Node.js will look like this:

$ node -e "console.log( JSON.stringify( JSON.parse(require('fs').readFileSync(0) ), 0, 1 ))"

For example:

$ cat test.json | node -e "console.log( JSON.stringify( JSON.parse(require('fs').readFileSync(0) ), 0, 1 ))"

Upvotes: 13

Fangxing
Fangxing

Reputation: 6105

Use Ruby in one line:

echo '{"test":1,"test2":2}' | ruby -e "require 'json'; puts JSON.pretty_generate(JSON.parse(STDIN.read))"

And you can set an alias for this:

alias to_j="ruby -e \"require 'json';puts JSON.pretty_generate(JSON.parse(STDIN.read))\""

Then you can use it more conveniently

echo '{"test":1,"test2":2}' | to_j

{
  "test": 1,
  "test2": 2
}

And if you want display JSON with color, your can install awesome_print,

gem install awesome_print

then

alias to_j="ruby -e \"require 'json';require 'awesome_print';ap JSON.parse(STDIN.read)\""

Try it!

echo '{"test":1,"test2":2, "arr":["aa","bb","cc"] }' | to_j

Enter image description here

Upvotes: 14

Dave Dopson
Dave Dopson

Reputation: 42684

I wrote a tool that has one of the best "smart whitespace" formatters available. It produces more readable and less verbose output than most of the other options here.

underscore-cli

This is what "smart whitespace" looks like:

I may be a bit biased, but it's an awesome tool for printing and manipulating JSON data from the command-line. It's super-friendly to use and has extensive command-line help/documentation. It's a Swiss Army knife that I use for 1001 different small tasks that would be surprisingly annoying to do any other way.

Latest use-case: Chrome, Dev console, Network tab, export all as HAR file, "cat site.har | underscore select '.url' --outfmt text | grep mydomain"; now I have a chronologically ordered list of all URL fetches made during the loading of my company's site.

Pretty printing is easy:

underscore -i data.json print

Same thing:

cat data.json | underscore print

Same thing, more explicit:

cat data.json | underscore print --outfmt pretty

This tool is my current passion project, so if you have any feature requests, there is a good chance I'll address them.

Upvotes: 359

Evgeny Karpov
Evgeny Karpov

Reputation: 2466

a simple bash script for pretty json printing

json_pretty.sh

#/bin/bash

grep -Eo '"[^"]*" *(: *([0-9]*|"[^"]*")[^{}\["]*|,)?|[^"\]\[\}\{]*|\{|\},?|\[|\],?|[0-9 ]*,?' | awk '{if ($0 ~ /^[}\]]/ ) offset-=4; printf "%*c%s\n", offset, " ", $0; if ($0 ~ /^[{\[]/) offset+=4}'

Example:

cat file.json | json_pretty.sh

Upvotes: 93

knb
knb

Reputation: 9285

With Perl, use the CPAN module JSON::XS. It installs a command line tool json_xs.

Validate:

json_xs -t null < myfile.json

Prettify the JSON file src.json to pretty.json:

< src.json json_xs > pretty.json

If you don't have json_xs, try json_pp . "pp" is for "pure perl" – the tool is implemented in Perl only, without a binding to an external C library (which is what XS stands for, Perl's "Extension System").

Upvotes: 77

jfs
jfs

Reputation: 414069

$ echo '{ "foo": "lorem", "bar": "ipsum" }' \
> | python -c'import fileinput, json;
> print(json.dumps(json.loads("".join(fileinput.input())),
>                  sort_keys=True, indent=4))'
{
    "bar": "ipsum",
    "foo": "lorem"
}

NOTE: It is not the way to do it.

The same in Perl:

$ cat json.txt \
> | perl -0007 -MJSON -nE'say to_json(from_json($_, {allow_nonref=>1}), 
>                                     {pretty=>1})'
{
   "bar" : "ipsum",
   "foo" : "lorem"
}

Note 2: If you run

echo '{ "Düsseldorf": "lorem", "bar": "ipsum" }' \
| python -c'import fileinput, json;
print(json.dumps(json.loads("".join(fileinput.input())),
                 sort_keys=True, indent=4))'

the nicely readable word becomes \u encoded

{
    "D\u00fcsseldorf": "lorem", 
    "bar": "ipsum"
}

If the remainder of your pipeline will gracefully handle unicode and you'd like your JSON to also be human-friendly, simply use ensure_ascii=False

echo '{ "Düsseldorf": "lorem", "bar": "ipsum" }' \
| python -c'import fileinput, json;
print json.dumps(json.loads("".join(fileinput.input())),
                 sort_keys=True, indent=4, ensure_ascii=False)'

and you'll get:

{
    "Düsseldorf": "lorem", 
    "bar": "ipsum"
}

What's more, you could make this a function in shell Using python script:

json_format(){
    python3 -c'import fileinput, json; \
        print(json.dumps(json.loads("".join(fileinput.input())), \
                sort_keys=True, indent=4, ensure_ascii=False))'
}

then you can use cat json.txt | json_format

Upvotes: 68

jordelver
jordelver

Reputation: 8432

UPDATE I'm using jq now as suggested in another answer. It's extremely powerful at filtering JSON, but, at its most basic, also an awesome way to pretty print JSON for viewing.

jsonpp is a very nice command line JSON pretty printer.

From the README:

Pretty print web service responses like so:

curl -s -L http://<!---->t.co/tYTq5Pu | jsonpp

and make beautiful the files running around on your disk:

jsonpp data/long_malformed.json

If you're on Mac OS X, you can brew install jsonpp. If not, you can simply copy the binary to somewhere in your $PATH.

Upvotes: 60

Techie
Techie

Reputation: 9494

You only need to use jq

If jq is not installed then you need to install jq first:

sudo apt-get update
sudo apt-get install jq

After installing jq then only need to use jq:

echo '{ "foo": "lorem", "bar": "ipsum" }' | jq

Output looks like

{
  "foo": "lorem",
  "bar": "ipsum"
}

Upvotes: 50

darscan
darscan

Reputation: 963

Or, with Ruby:

echo '{ "foo": "lorem", "bar": "ipsum" }' | ruby -r json -e 'jj JSON.parse gets'

Upvotes: 44

Arpit Rathod
Arpit Rathod

Reputation: 101

You can use this simple command to achieve the result:

echo "{ \"foo\": \"lorem\", \"bar\": \"ipsum\" }"|python -m json.tool

Upvotes: 42

Salman Arshad
Salman Arshad

Reputation: 272006

JSONLint has an open-source implementation on GitHub that can be used on the command line or included in a Node.js project.

npm install jsonlint -g

and then

jsonlint -p myfile.json

or

curl -s "http://api.twitter.com/1/users/show/user.json" | jsonlint | less

Upvotes: 31

htaccess
htaccess

Reputation: 3100

I recommend using the json_xs command line utility which is included in the JSON::XS perl module. JSON::XS is a Perl module for serializing/deserializing JSON, on a Debian or Ubuntu machine you can install it like this:

sudo apt-get install libjson-xs-perl

It is obviously also available on CPAN.

To use it to format JSON obtained from a URL you can use curl or wget like this:

$ curl -s http://page.that.serves.json.com/json/ | json_xs

or this:

$ wget -q -O - http://page.that.serves.json.com/json/ | json_xs

and to format JSON contained in a file you can do this:

$ json_xs < file-full-of.json

To reformat as YAML, which some people consider to be more humanly-readable than JSON:

$ json_xs -t yaml < file-full-of.json

Upvotes: 20

Uma sankar pradhan
Uma sankar pradhan

Reputation: 419

Install yajl-tools with the command below:

sudo apt-get install yajl-tools

then,

echo '{"foo": "lorem", "bar": "ipsum"}' | json_reformat

Upvotes: 17

Somu
Somu

Reputation: 3750

I use the "space" argument of JSON.stringify to pretty-print JSON in JavaScript.

Examples:

// Indent with 4 spaces
JSON.stringify({"foo":"lorem","bar":"ipsum"}, null, 4);

// Indent with tabs
JSON.stringify({"foo":"lorem","bar":"ipsum"}, null, '\t');

From the Unix command-line with Node.js, specifying JSON on the command line:

$ node -e "console.log(JSON.stringify(JSON.parse(process.argv[1]), null, '\t'));" \
  '{"foo":"lorem","bar":"ipsum"}'

Returns:

{
    "foo": "lorem",
    "bar": "ipsum"
}

From the Unix command-line with Node.js, specifying a filename that contains JSON, and using an indent of four spaces:

$ node -e "console.log(JSON.stringify(JSON.parse(require('fs') \
      .readFileSync(process.argv[1])), null, 4));"  filename.json

Using a pipe:

echo '{"foo": "lorem", "bar": "ipsum"}' | node -e \
"\
 s=process.openStdin();\
 d=[];\
 s.on('data',function(c){\
   d.push(c);\
 });\
 s.on('end',function(){\
   console.log(JSON.stringify(JSON.parse(d.join('')),null,2));\
 });\
"

Upvotes: 412

Related Questions