Reputation:
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
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
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
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
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
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
Reputation: 3423
You can use xidel.
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
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
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
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
Reputation: 10006
$ sudo apt-get install edit-json
$ prettify_json myfile.json
Upvotes: 5
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
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
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
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
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
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
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
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
Upvotes: 14
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.
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
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
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
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
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
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
Reputation: 963
Or, with Ruby:
echo '{ "foo": "lorem", "bar": "ipsum" }' | ruby -r json -e 'jj JSON.parse gets'
Upvotes: 44
Reputation: 101
You can use this simple command to achieve the result:
echo "{ \"foo\": \"lorem\", \"bar\": \"ipsum\" }"|python -m json.tool
Upvotes: 42
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
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
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
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