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

63

3657

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"
}
Knotty answered 9/12, 2008 at 8:20 Comment(13)
https://mcmap.net/q/37058/-how-to-quot-pretty-quot-format-json-outputPeashooter
I rolled my own a short while back: github.com/exhuma/braindump/tree/master/jsonformat The code is very simple, using python's own json library, but I added pygments as well to get syntax highlighting.Alvera
Stumbled on to this but then found Json Pretty and I quite like it. Typekit uses it in their API examples, so there's some klout behind it ^^Dillon
If you don't mind copying pasting, there's also some simple tools online like jsonprettyprint.net where you can quickly pretty print your raw JSON.Ait
Just a little cool tidbit that might be super obvious, but for anyone trying to pretty print a file containing JSON this works echo "$(cat nameOfYourFile.js)" | python -m json.toolDoelling
Be warned: python -m json.tool does not always produce valid JSON. (Hint: 1e1000)Papeterie
Is the json only one level deep? This cuts out regex based solutions in case of negative response.Karren
Anyone have a convenient way to pretty-print a JSON file in-place?Mover
@Mover here is interactive JSON viewer github.com/antonmedv/fxMultivibrator
Too many (identical) answers, it is hard to find a listing of possible solutions. I've made a benchmark to try and summarise those. I hope this won't be yet another useless answer!Ommatophore
If you want to format your json as a table, you can use jtab, a tool written in rust that allows you to do that: github.com/wlezzar/jtabHouphouetboigny
Also don't include -DCasia
use smart json which format json/json5 to compact json formatLeavings
J
5132

With Python 2.6+ or 3 you can use the json.tool module:

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

or, if the JSON is in a file, you can do:

python -m json.tool my_json.json

if the JSON is from an internet source such as an API, you can use

curl http://my_url/ | python -m json.tool

For convenience in all of these cases you can make an alias:

alias prettyjson='python -m json.tool'

For even more convenience with a bit more typing to get it ready:

prettyjson_s() {
    echo "$1" | python -m json.tool
}

prettyjson_f() {
    python -m json.tool "$1"
}

prettyjson_w() {
    curl "$1" | python -m json.tool
}

for all the above cases. You can put this in .bashrc and it will be available every time in shell. Invoke it like prettyjson_s '{"foo": "lorem", "bar": "ipsum"}'.

Note that as @pnd pointed out in the comments below, in Python 3.5+ the JSON object is no longer sorted by default. To sort, add the --sort-keys flag to the end. I.e. ... | python -m json.tool --sort-keys.

Another useful option might be --no-ensure-ascii which disables escaping of non-ASCII characters (new in version 3.9).

Junket answered 9/12, 2008 at 8:20 Comment(35)
With other versions of Python you can install simplejson and use python -msimplejson.toolPhonetic
You could pipe that onto pygmentize -l javascript to get syntax colored output in your command line. Edit: If you have pygments installed that is.Haddock
alias ppj='python -mjson.tool'; echo '{"foo": "lorem", "bar": "ipsum"}' | ppjIrons
A great answer, only caution I have with it is it does sort the keys on output - which you might need to be aware of.Koenraad
In myy .vimrc "nnoremap <f5> :%!python -m json.tool<CR>:w<CR>"Aeropause
This seems to escape Unicode characters into \uXXXX, which might be a disadvantage.Exhilaration
This is tip is super handy when viewing Riak or (other JSON-capable servers) output! e.g. curl blah.com:8089 | python -mjson.tool You absolutely don't need to install or configiure anything except python, which is usually there already.Zondra
hey can anyone help with adding this as a external command in gedit? Edit: got it; Tools -> Manage External Toosl -> new (+) -> add "python -mjson.tool " -> Select Input = Current Document, Output = Replace Current Document. Cheers!Hecatomb
Anyone got the same for XML?Dorris
@MikeWeller #16091369Vying
and add syntax highlighting by piping the output into 'colout -t json'. Requires 'pip install colout' first.Copolymer
@Exhilaration To keep the Unicode characters in the output it is necessary to make your own script. import sys import json j = json.load(sys.stdin) json.dump(j, sys.stdout, ensure_ascii=False, sort_keys=True, indent=4, separators=(',', ': '))Bloomers
It doesn't accept top level arrays, so not all json sadly.Counterman
@ShrikantSharat: since version 1.5 Pygments support json type as well.Loos
I've created an alias: alias pretty='python -mjson.tool | pygmentize -l json so that I can just run: command params | pretty. Hope this helps. PS: Should anyone manages to extend this to a) remove the curl-output I'm seeing every time and/or b) NOT sort the json keys; please do let me know, I will be highly thankful.Jannette
And if the JSON is in a file: $ cat file.json | python -m json.toolZinc
Another problem with python -m json.tool as a JSON pretty-printer is that it does not always print valid JSON values. E.g. 1e1000 is converted to Infinity.Papeterie
python does not support non-asciiMute
Changed in Python 3.5: Output now same order as Input. Use --sort-keys to sort keys alphabetically. In response to comment by @ChrisNash.Gussy
If you're on macOS and you have some json on the clipboard that you want formatted pbpaste | python -m json.tool | pbcopy.Shaunta
Amazing! Thanks for sharing this. Also, in case you have passed in the "-i" option to cURL, it won't be able to pretty print the json as you have now got HTTP headers as well.Benisch
What if I want to cat it using python -m json.tool /path.json?Norwegian
Is there a way to format the brackets in a better way? (Use same column for the left bracket and the corresponding right bracket)Volkman
@ClintEastwood - the curl -s option will supress the output e.g. curl -s http://my_url/ | python -m json.tool Should just print the JSON.Sulphuric
This effectively just answers how to do it in Python, or on the web. The letter of the question seems to be satisfied, but I don't think the spirit of it has been at all. 3,551 upvotes seems like a gross overreaction.Kauai
which module is required to be installed? I get: /usr/bin/python: No module named json.moduleSarcous
@ClintEastwood To suppress the progress report / bar of curl, just pass the silent flag: curl -sChapin
is this the highest voted unaccepted answer of all timeGerstein
The technique from this answer, for all .json files in your current directory: for file in *.json; do python -m json.tool $file > ${file/.json/.pretty.json}; doneCrossquestion
json.tool does not work well for large files. There is a fp.read() in there somewhere reading the entire JSON file.Propagandism
This does not work if your json contains unicode. Pretty sad that this is the most up voted answer.Schlesinger
I just want to add that to anyone who cannot print no ascii values with this approach that as of python >=3.9 you can do: $ python -m json.tool --no-ensure-ascii to print them.Ambassadress
Since python 3 is default for Ubuntu, the new alias is: alias pretty='python3 -mjson.tool | pygmentize -l json'Salmonberry
@Exhilaration run it with --no-ensure-asciiJunket
How can I use this to write to the file in place?Patmore
B
1542

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"
Buchner answered 9/12, 2008 at 8:20 Comment(19)
There is also a --sort-keys option, which is helpful in some cases.Eliseoelish
jq is a great tool, which I discovered through this answer. Be aware however that it requires whole objects to work on. It won't start outputting results until it has read in the whole input object.Slivovitz
Working with curl: curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.'Promiscuous
"jq ." is great as a pretty-printer, but it comes with a caveat: jq (up to and including jq version 1.5) will alter the values of very large and very small numbers because it parses numeric values as IEEE 754 64-bit values. To check whether your favorite pretty-printer has the same issue, try this value: 1e1000. Note that python -mjson.tool fails this test badly in that it produces Infinity, which is not even JSON.Papeterie
As a note, you can redirect the formatted result to a file: echo '{ "foo": "lorem", "bar": "ipsum" }' | jq . > myfile.Jeanette
@Meekohi the alternative is "unnecessary use of echo". Super happy to have found the <<< operator – exactly what I was looking for.Peoria
Here's a nice runthru of jq's features, including a section on pretty-printing: shapeshed.com/jq-json/#how-to-pretty-print-json. One way to write your ugly file to a pretty one: cat ugly.json | jq '.' | cat > pretty.jsonViolative
Typing cat | jq . and then pasting used to work. No longer, it seems... jq just exits for some reason. Now I use my paste-from-clipboard alias: clipread | jq. The alias is alias clipread='xclip -out -selection clipboard' (add this to your ~/.bashrc or zshrc or whatever-rc, and choose an alias name that you like).Cant
Reading from a file jq . <<< cat filename.jsonLanielanier
jq is the best because it prints in colors!Pro
@Cant . Try cat - | jq . with pasted text. Good luck to all.Livable
jq -C to include colors. If you piping the output to less, then export LESS="-R" and then use jq -C ... | less. Without -C, jq suppresses colors when the output is not directed to a terminal, as in | command or > file.Oxidate
jq has the irritating property that it will silently loose precision on numbers. E.g. if your input has "foo": 16962331779841739123 then jq '.' will silently round the number to "foo": 16962331779841739000. If I'm only looking for a pretty-printer, then I'd chose one that's not lossy.Bursa
+1 unlike the python solution, jq also handles some improperly formatted data (e.g. Ubiquiti's NVR backup files) like this: echo '{"foo":0}{"bar":1}' | jq where python chokes on the missing comma and gives no formatted output.Kneepan
echo '{"value": 1e1000}' | fx .valueMultivibrator
Why on earth is this answer with more than 1000 upvotes hidden on page 2? jq is by far one of the best tools for the job. Stack Overflow needs to improve its answer sorting algorithm.Statant
On macOS: brew install jqBeefburger
Inspired by @HoverRuan and this, remove .: curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jqPaleolithic
I also like pbpaste | jqServe
C
412

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));\
 });\
"
Concession answered 9/12, 2008 at 8:20 Comment(12)
For debugging objects in Node.js, you should really use sys.inspect() instead of JSON.stringify(). Here's why: markhansen.co.nz/inspecting-with-json-stringifyDunno
Downvoted. The OP is about a "*nix command-line script" and this answer is a different context.Micturition
@danorton: JS can be used from the commandline via node.js and other similar solutions.Dipteran
Use node -e "console.log(JSON.stringify(JSON.parse(process.argv[1]), null, '\t'));" on the Unix command-line (with nodejs)Concession
node -e 'var f = require("./package.json"); console.log(f.name);' Even shorter :D :D :DBryannabryansk
No need for the console: node -p "JSON.stringify(JSON.parse(process.argv[1]), null, '\t');" also outputs the result to STDOUT.Curtate
JSON.stringify i always useAndrus
It sucks that the script is different for a filename vs. stdinWaverly
@LukaszWiktor it doesn't have to be if your *nix supports /dev/stdin!Pulling
Why don't you use require('util').inspect(JSON.parse(obj))? It provides pretty printing, colors and a bunch of other featuresCitric
the article @GurpartapSingh linked is not available anymore. for anyone who wanted to read it, here's the most recent capture from the wayback machineAstronautics
@GurpartapSingh your link is dead. That's why I don't like external links.Ambrosius
S
358

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.

Some answered 9/12, 2008 at 8:20 Comment(6)
I also updated my ~/.bash_profile to have the following line: alias underscor='underscore print --outfmt pretty' now I can just do curl example.com/result.json | underscor and still use underscore for other formattingCornfield
Thanks Dave! Tool is good! alias pretty-json="underrsore pretty" and curl output pleasing an eyeWarenne
Great formatting tool, just one note: forwarding output to a file (either with -o option or with > ) works only with underscore print. underscore pretty saves a file with color formatting signs being inserted, smth like: [32m, [33m, [39m along with some non-printable before each of them, which makes JSON not valid. However, underscore print alone doesn't add anything to a file and does its formatting job perfectly.Apology
I love jq but this worked great for my "JSON" that didn't have double quoted keys.Annal
@DaveDopson thanks for the great tool!! Gonna try using it alongside jsonselect.org/#tryit ...Baton
Also, using npm (use creationix/nvm :) ) to install, because it should be global: npm install -g underscore-cli ... then in .bash_profile: alias json='underscore print --color' ... and use like: cat some.json | json Underscore-CLI is really great and easy to integrate into your development environment.Aggravation
A
185

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 -mjson.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
Accountable answered 9/12, 2008 at 8:20 Comment(3)
if the json is supposed to come directly froma http api this is also a nice tool implemented in python: github.com/jkbr/httpieLenient
If you have node installed (and don't mind the YAML style output) there's also this package: rafeca.com/prettyjson so you can end a curl with | prettyjsonDenunciatory
As noted above, one of the problems with python -mjson.tool as a JSON pretty-printer is that it does not always emit JSON. E.g. 1e1000 becomes Infinity (whether using python 2.x or 3.x). 'jq .' always produces JSON, but it does not guarantee that very large (or very small values) are preserved exactly.Papeterie
C
104

If you use npm and Node.js, you can do npm install -g json and then pipe the command through json. Do json -h to get all the options. It can also pull out specific fields and colorize the output with -i.

curl -s http://search.twitter.com/search.json?q=node.js | json
Concentrated answered 9/12, 2008 at 8:20 Comment(0)
H
101

It is not too simple with a native way with the jq tools.

For example:

cat xxx | jq .
Hendricks answered 9/12, 2008 at 8:20 Comment(3)
WARNING: jq encodes numbers as IEEE 754 64-bit floats, and thus their representation is likely to change. The precision of very small and very large numbers is likely to be lost. To check whether your favorite pretty-printer has the same issue, try this value: 1e1000.Papeterie
or simply: jq . file.json ; but also cat file.json | jq (without the filter .) also works. (on ubuntu/linux; ymmv across platforms)Sorenson
Already installed in Ubuntu and colors as well. NiceAnatolia
K
95

Thanks to J.F. Sebastian's very helpful pointers, here's a slightly enhanced script I've come up with:

#!/usr/bin/python

"""
Convert JSON data to human-readable form.

Usage:
  prettyJSON.py inputFile [outputFile]
"""

import sys
import simplejson as json


def main(args):
    try:
        if args[1] == '-':
            inputFile = sys.stdin
        else:
            inputFile = open(args[1])
        input = json.load(inputFile)
        inputFile.close()
    except IndexError:
        usage()
        return False
    if len(args) < 3:
        print json.dumps(input, sort_keys = False, indent = 4)
    else:
        outputFile = open(args[2], "w")
        json.dump(input, outputFile, sort_keys = False, indent = 4)
        outputFile.close()
    return True


def usage():
    print __doc__


if __name__ == "__main__":
    sys.exit(not main(sys.argv))
Knotty answered 9/12, 2008 at 8:20 Comment(5)
When the values are loaded into the dictionary, the order is lost: normal dict objects do not have a defined order. Try json.dumps(json.loads('{"b": 1, "a": 2}'), sort_keys=False) and you'll find they're swapped anyway. To fix it, import OrderedDict and load passing object_pairs_hook=OrderedDict.Islamite
You can change the script to read from standard input with this: inputFile = sys.stdin. This lets you pipe stuff to the script like so: curl http://somewhere.com/foo.json | pp_json.pyAntung
And to avoid sorting with @icktoofay's comment, import OrderedDict like this: from collections import OrderedDict.Arther
Thanks @icktoofay. This allowed me to create the following vim function: com! FormatJSON %!python -c "from collections import OrderedDict; import sys; import json; j = json.load(sys.stdin, object_pairs_hook=OrderedDict); json.dump(j, sys.stdout, sort_keys=False, indent=4, separators=(',', ': '))" Note that the separators must be set as (',', ': ') to avoid trailing whitespace being added: bugs.python.org/issue16333Gird
Great snippet! I've used sort_keys = True instead, because I want to use this to compare json files and it works like a charm.Lowestoft
A
86

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
Antlion answered 9/12, 2008 at 8:20 Comment(16)
Thanks for the feedback. I just wrote this script today for personal using and it worked fine in my cases. I made fixes, now it's smaller and without this problem. There is not a goal to support completely format, but i can make other fixes if necessary.Antlion
That is only working answer I found. I have an embedded linux - no rubby, no javascript, no access to internet to download python modules... I have slightly different awk that does not support %*c notation so I changed the printf to c=0; while (c++<offset) printf " "; printf $0;. And my awk has different regex escaping and backslash does not work in []. I changed the regexes to /^[[{]/ and /[]}]/.Saxena
This should be the accepted, as it's full native and don't require third party software...Miele
@Miele the script looked broken after your editing, please explain or correct it. thanks!Antlion
@EvgenyKarpov nice catch, no need for a full rollback, just the grep that was erased by mistake ;)Miele
This script is pretty fragile and it doesn't support full json syntax. For example it turns { "\"" : "quote" } into { "\" " : " } (on multiple lines).Lexicostatistics
This works pretty well with piping. getMyLogs | grep -Eo ...Murrelet
Thanks dude, I wanted a quick way to format an 8MB one-liner json, in bare simple bash.Equivalent
In my case, I also needed to execute json_pretty.sh, e.g. cat file.json | ./json_pretty.shOxidase
Best solution if you have a stand-alone script and you don't want to make someone install Homebrew, python, ruby, node.js...Martellato
Really good answer. This is the only method that worked for me to deal with a broken json oneline file. ThanksCoorg
@UrsineRaven feel free to bring your changes to the post if it brings improvementsAntlion
@EvgenyKarpov I apparently need 100 reputation to do that, but I also just noticed that I should have changed [0-9 ]*,? to [0-9]+ *,?|, instead of [0-9]+ *,?, so that we don't lose the commas after arrays in objects (i.e. with my above comment, we lose the comma after ] in {"a":[1,2],"b":"c"}). So, I guess I'll just have to delete my comment and repost it with the fix for now.Pathic
I made @ZabojCampula's changes (also necessary for me) and I also made a fix for what @Lexicostatistics mentioned and came up with this: grep -Eo '"([^"\]*(\\")*(\\[^"])*)*" *(: *([0-9]*|"([^"\]*(\\")*(\\[^"])*)*")[^{}\["]*|,)?|[^"\]\[\}\{]*|\{|\},?|\[|\],?|[0-9]+ *,?|,' | awk '{if ($0 ~ /^[]}]/ ) offset-=4; c=0; while (c++<offset) printf " "; printf "%s\n",$0; if ($0 ~ /^[[{]/) offset+=4}'. To fix the { "\"" : "quote" } test case, I changed the instances of "[^"]*" to "([^"\]*(\\")*(\\[^"])*)*" and changed [0-9 ]*,? to [0-9]+ *,?|, at end of grep regex (prevent empty lines from test case)Pathic
I ended up making a script (based on the JSON definition on json.org) that should be mostly language complete for JSON and pretty-prints the JSON that is piped into it.Pathic
The great thing about this is that unlike the higher ranking answers, it actually doesn't fail on encountering unprintable characters! Kudos!Charolettecharon
I
77

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

Irade answered 9/12, 2008 at 8:20 Comment(6)
Seems to come standard with Cygwin!Nippers
json_pp can be used in the same way and is most probably readily installed on your system (on Debian it is in the 'perl' package).Stemma
FYI, on my Mac OS X 10.9 system, json_pp is available automatically.Spell
-t null gave me null: not a valid toformat... but leaving it off worked splendidly. Thanks.Drill
pp is for pure perl, not pretty print here :) Since json_xs and json_pp can do more than just pretty print and also with -json_opt do other things instead of pretty printing. Although pretty printing is the default behaviour.Madisonmadlen
json_xs and json_pp neither preserve key order nor sort the keys. Pretty-printing the same JSON file twice is likely to produce different results. (Tested with perl-5.26.1-6 and libjson-xs-perl-3.040-1 on Ubuntu 18.04.)Juice
K
75

That's how I do it:

curl yourUri | json_pp

It shortens the code and gets the job done.

Kowal answered 9/12, 2008 at 8:20 Comment(3)
Ubuntu server: If you have production machines with very restricted installations, this might be the best choice as it is installed by default under a specific name. Python is often installed in different ways (eg python3, python or not at all) depending on the version.Subinfeudation
works for mac :)Inamorato
Works for both MacOS and Linux (Debian) by default. I'd recommend this answerTeter
N
74

On *nix, reading from stdin and writing to stdout works better:

#!/usr/bin/env python
"""
Convert JSON data to human-readable form.

(Reads from stdin and writes to stdout)
"""

import sys
try:
    import simplejson as json
except:
    import json

print json.dumps(json.loads(sys.stdin.read()), indent=4)
sys.exit(0)

Put this in a file (I named mine "prettyJSON" after AnC's answer) in your PATH and chmod +x it, and you're good to go.

Nighthawk answered 9/12, 2008 at 8:20 Comment(5)
Indeed, using stdin/stdout is much more flexible and simple. Thanks for pointing it out.Knotty
For programs that expect a named file, use /dev/stdin, ditto for out and err.Luncheonette
FYI fileinput.input() reads from stdin if there are no files given at a command-line. ExampleQuaff
fileinput.input() can't deal well with files with no newline at the end, last time I checked.Spelt
he askes in shell script, not python other language. With JQ can do it perfectly.Radiolucent
M
68

The JSON Ruby Gem is bundled with a shell script to prettify JSON:

sudo gem install json
echo '{ "foo": "bar" }' | prettify_json.rb

Script download: gist.github.com/3738968

Murmur answered 9/12, 2008 at 8:20 Comment(6)
Note that this solution decode the unicode "\uxxxx" escape sequences, unlike the Python one with json.tool. However, it also seems to have nesting depth limitations (nesting of 20 is too deep (JSON::NestingError)).Teat
on Ubuntu you can do: sudo apt-get install ruby-json-pure instead of gem installNippers
```eric-mbp:~ ericstob$ sudo gem install json Password: Fetching: json-1.7.3.gem (100%) Building native extensions. This could take a while... Successfully installed json-1.7.3 1 gem installed Installing ri documentation for json-1.7.3... Installing RDoc documentation for json-1.7.3... eric-mbp:~ ericstob$ prettify_json.rb -bash: prettify_json.rb: command not foundSettler
maybe you could post the contents of your prettify_json.rb?Matchbox
You can download the script, move it to your ~/bin folder (make sure it's in your PATH) rename prettify_json.rb to ppj and run chmod +x ppj. Now you can do something like curl www.jsonsring.com/something.json | ppjGripe
prettify_json.rb ships with Ruby 1.9 and laterEugene
Q
68
$ 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

Quaff answered 9/12, 2008 at 8:20 Comment(6)
actually I do the same but with javascript itself :)Alduino
In the version of the JSON module I have, to_json doesn't seem to accept options. But this works: perl -MJSON -nE 'say JSON->new->pretty->encode(from_json $_)' text.jsonBedsore
The Python example could be simplified. It's much easier to pipe JSON output straight into python -m json.tool.Diskson
@Dan: yes. And there are several answers that show json.tool code examples. 1. this version allows you to change some parameters e.g., indent 2. At the time of the posting (2008) Python 2.4 was still used that doesn't support -mjson.toolQuaff
@dwlz command-line version with unicode characters (requires python3.9+): python -m json.tool --no-ensure-ascii in.json out.jsonAl
json_format(){ python3 -c'import fileinput, json; \ print(json.dumps(json.loads("".join(fileinput.input())), \ sort_keys=True, indent=4, ensure_ascii=False))' } make this a function, cat example.json | json_formatIsauraisbel
L
60

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.

Livy answered 9/12, 2008 at 8:20 Comment(3)
I tried jsonpp (used in the past successful) against a huge file (>60MB). I stopped it after 5min. I piped it into python -mjson.tool (from other answer here) and it took 10-20sec...Herc
60MB of JSON? Wow! I don't typically deal with files that big but useful to know. Thanks.Livy
On my ubuntu box I have a json_pp - which does format json nicely, although despite the similarity in naming, I believe this to be an entirely different project from the jsonpp mentioned hereLanell
R
54

Try pjson. It has colors!

echo '{"json":"obj"} | pjson

Install it with pip:

⚡ pip install pjson

And then pipe any JSON content to pjson.

Revanche answered 9/12, 2008 at 8:20 Comment(3)
It requires python-pip (sudo apt-get install python-pip) and then (sudo pip install pjson) The great advantage are colours!Datcha
The disadvantage is it is not possible to grep coloured output.Datcha
How can I use this tool to read from a file and format it in-place, writing back to the same file?Patmore
S
47

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"
}
Speedway answered 9/12, 2008 at 8:20 Comment(2)
Or brew install jq if you're on a mac.Menken
How can I use jq to read from a file and write to that same file in-place?Patmore
G
44

Or, with Ruby:

echo '{ "foo": "lorem", "bar": "ipsum" }' | ruby -r json -e 'jj JSON.parse gets'
Glanville answered 9/12, 2008 at 8:20 Comment(4)
That gives me an error. Do you need some ruby json package installed?Marra
Yes, you need the JSON Ruby Gem: sudo gem install jsonGlanville
@MatSchaffer Note that this does not work if you are using JSON to serialize objects with custom to_json methods; Kernel#jj only pretty-prints arrays and hashes of the same (or numbers/strings/booleans).Ladon
On Windows, try this: echo { "foo": "lorem", "bar": "ipsum" } | ruby -r json -e 'jj JSON.parse gets'Borkowski
C
42

You can use this simple command to achieve the result:

echo "{ \"foo\": \"lorem\", \"bar\": \"ipsum\" }"|python -m json.tool
Copalm answered 9/12, 2008 at 8:20 Comment(3)
Best answer in my opinion. Small and easy to remember and doesn't require installing any non-standard tools.Grandnephew
python -m json.tool doesn't seem to preserve the order of the JSON object.Biceps
It do sorting in python 2, in 3 it does not sort github.com/python/cpython/blob/3.8/Lib/json/tool.pyVashti
M
41

I use jshon to do exactly what you're describing. Just run:

echo $COMPACTED_JSON_TEXT | jshon

You can also pass arguments to transform the JSON data.

Mitchel answered 9/12, 2008 at 8:20 Comment(3)
Thanks, jshon is a lot faster than using python or ruby for the same taskCrying
@Crying - How fast a pretty printer do you need? I'm on OSx Lion that comes with Python preinstalled. With python -mjson.tool I can pretty print a 96KB json file in 0.1s - the json output of earthporn that jshon links to is about 24KB and I can pretty print that in 0.08s. How much faster is jshon for you?Pterodactyl
I'm working with 1+GB compressed (who even knows how big uncompressed) JSON data files, so I very much appreciate the suggestion that jshon is faster.Sadism
A
39

Check out Jazor. It's a simple command line JSON parser written in Ruby.

gem install jazor
jazor --help
Argyrol answered 9/12, 2008 at 8:20 Comment(3)
Is it just me or is this the only suggestion that actually answers the OP's question? I came here looking for a simple command into which I could pipe the output of curl and this is the only one that did it for me.Vincentvincenta
I like that it has the option to colorize the output. Makes it easier to read.Matchbox
ooh I also like the option to pass a url since I am using this to view the output of my REST APIMatchbox
S
31

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
Stefanistefania answered 9/12, 2008 at 8:20 Comment(1)
I recommend not installing nodejs/npm dependencies globally => I'd use npx instead: curl -s "http://api.twitter.com/1/users/show/user.json" | npx jsonlint | less (i.e. no npm install necessary)Naldo
N
29

You can simply use standard tools like jq or json_pp.

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

or

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

will both prettify output like the following (jq even more colorful):

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

The huge advantage of jq is that it can do A LOT more if you'd like to parse and process the json.

Nuzzi answered 9/12, 2008 at 8:20 Comment(2)
json_pp was on my Mac - but not jq. Thanks!Anatol
@DavidH - does this help: #37668634Nuzzi
L
29

Simply pipe the output to jq ..

Example:

twurl -H ads-api.twitter.com '.......' | jq .
Linearity answered 9/12, 2008 at 8:20 Comment(4)
Nice answer @Ackshaey Singh and one can re-direct the same to a file easily as well. e.g. cat <file_name.txt> | jq . > <output_name.txt>Merimerida
brew install jq if your are on mac os.Demigod
Unfortunately, using jq . for pretty-printing has one potential drawback: all extant versions of jq insist on treating JSON numbers as IEEE numbers, so precision is easily lost, e.g. for very large integers.Papeterie
@Merimerida cat file | is invariably a waste of a process; just do jq . <file_name.txt >output_name.txt (with literal < and > characters).Ambrosio
T
25

Pygmentize

I combine Python's json.tool with pygmentize:

echo '{"foo": "bar"}' | python -m json.tool | pygmentize -g

There are some alternatives to pygmentize which are listed in my this answer.

Here is a live demo:

Demo

Turboelectric answered 9/12, 2008 at 8:20 Comment(2)
Sometimes one needs to use pygmentize -l json to get colourfication.She
Install with apt package python-pygments, i.e. apt-get install python-pygmentsDrumfire
G
25

With Perl, if you install JSON::PP from CPAN you'll get the json_pp command. Stealing the example from B Bycroft you get:

[pdurbin@beamish ~]$ echo '{"foo": "lorem", "bar": "ipsum"}' | json_pp
{
   "bar" : "ipsum",
   "foo" : "lorem"
}

It's worth mentioning that json_pp comes pre-installed with Ubuntu 12.04 (at least) and Debian in /usr/bin/json_pp

Gilletta answered 9/12, 2008 at 8:20 Comment(0)
P
20

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.

Papeterie answered 9/12, 2008 at 8:20 Comment(0)
O
20

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
Oread answered 9/12, 2008 at 8:20 Comment(0)
G
17

When you have node installed on your system the following works.

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

{
  "test": 1,
  "test2": 2
}
Garate answered 9/12, 2008 at 8:20 Comment(0)
P
17

bat is a cat clone with syntax highlighting:

Example:

echo '{"bignum":1e1000}' | bat -p -l json

-p will output without headers, and -l will explicitly specify the language.

It has colouring and formatting for JSON and does not have the problems noted in this comment: How can I pretty-print JSON in a shell script?

Pocketknife answered 9/12, 2008 at 8:20 Comment(0)
C
17

Install yajl-tools with the command below:

sudo apt-get install yajl-tools

then,

echo '{"foo": "lorem", "bar": "ipsum"}' | json_reformat
Charlet answered 9/12, 2008 at 8:20 Comment(1)
Awesome. Does not require another language/interpreter and is in the package repo's, no need to brew!Mailable
H
16
  1. brew install jq
  2. command + | jq
  3. (example: curl localhost:5000/blocks | jq)
  4. Enjoy!

enter image description here

Hesper answered 9/12, 2008 at 8:20 Comment(0)
H
13

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 ))"
Howie answered 9/12, 2008 at 8:20 Comment(2)
no output for me with this example even though I voted this up long time ago. Something changed ...Murrelet
@MatthisKohli: I just rechecked this on Node V12.x and it is working. There is nothing magic in this code. fs.readFileSync(0) reads stdin of the current process and JSON.stringify formats the JSON. So, there is very less chance for breaking API changeHowie
S
13

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

Swadeshi answered 9/12, 2008 at 8:20 Comment(0)
J
10

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"
}
Jokjakarta answered 9/12, 2008 at 8:20 Comment(0)
S
10

yajl is very nice, in my experience. I use its json_reformat command to pretty-print .json files in vim by putting the following line in my .vimrc:

autocmd FileType json setlocal equalprg=json_reformat
Subchloride answered 9/12, 2008 at 8:20 Comment(0)
O
9

TL;DR: for performances, use jj -p < my.json.

Benchmark

I took some solutions here and benchmarked them with the next dummy script:

function bench {
    time (
      for i in {1..1000}; do
        echo '{ "foo" : { "bar": { "dolorem" : "ipsum", "quia" : { "dolor" : "sit"} } } }' \
        | $@ > /dev/null
      done
    )
}

Here's the result on my mac (32 GB, Apple M1 Max, YMMV):

bench python -m json.tool
# 8.39s user 12.31s system 42% cpu 48.536 total
bench jq
# 13.12s user 1.28s system 87% cpu 16.535 total
bench bat -p -l json # NOTE: only syntax colorisation.
# 1.87s user 1.47s system 66% cpu 5.024 total
bench jj -p
# 1.94s user 2.44s system 57% cpu 7.591 total
bench xidel -s - -e '$json' --printed-json-format=pretty                      
# 4.32s user 1.89s system 76% cpu 8.101 total

Thanks @peak and your answer for this discovery of jj!

Ommatophore answered 9/12, 2008 at 8:20 Comment(13)
Great, but it would be even nicer if it were a more complex and longer JSON test string.Ejective
@HiltonFernandes feel free to edit :)Ommatophore
Dear @Ulysse BN, if I do edit it to add more complexity to the JSON string, would you please try to run your benchmark again ? Unfortunately I don't have a mac (8 GB 2133 MHz LPDDR3, 2.3 GHz Intel Core i5) at hand here.Ejective
@HiltonFernandes me neither anymore! But sure I could install stuff and run the benchmark. I'm on an M1 chip now though, so YMMV... BTW steps to install and run the benchmark on a mac: (1.) brew install jq bat tidwall/jj/jj xidel, (2.) copy and paste the function block, (3.) copy and paste the bench block, (4.) edit this post with your configuration (about my mac). Also please, no need to be complacent, I get the gist...Ommatophore
Hello, @Ulysse BN, your idea is great and its implementation is very elegant. Congrats also to your M1 powered Mac. Please consider my suggestion of a benchmark in gist.github.com/hgfernan/716f599503c21d56ca141da04349ffa1Ejective
@HiltonFernandes there you goOmmatophore
Many thanks for accepting my suggestion, @Ulysse BN ! Would you mind if I ask you what have been the changes in your benchmark list ?Ejective
@HiltonFernandes you can see changes via the link below the answer (edited some time ago)Ommatophore
For everyone reading this; the Xidel version used here (v0.9.8) is NOT the recommended binary to use. Binaries from the development branch are, eventhough they might be considered beta! The latest Xidel dev-build is aprox. 3.5-4.5x faster than v0.9.8 in this particular benchmark.Enrica
@Enrica I've finally installed xidel 0.9.9, it has a lot of dependencies and is not packaged efficiently (TL;DR: brew install xidel --head and feel the svn pain). However I'll have to admit, it is fast (5s, beats jj). I'd still not advise it: the installation process is heavy, and the the build is yet to be official... DISCLAIMER: I'll stop editing this post from now on. I've added enough information in the comment for anyone else to do it, so please do! I'm not paid more than you to do that.Ommatophore
Great @UlysseBN ! I was wondering that in your original form, the cost of starting lots of light threads could become stronger than the pretty printing itself. Now that each run do a little more work, the thread startup cost is probably proportionally smaller.Ejective
BTW, sorry to have abused of your time, @UlysseBN. People got very interested in your post.Ejective
There's no need to compile Xidel yourself when there are lots of pre-compiled binaries available. I'm not a Linux user, but if you're referring to github.com/Homebrew/homebrew-core/blob/master/Formula/xidel.rb, it's outdated and using the wrong sources. The pre-compiled Linux binaries only rely on OpenSSL afaik.Enrica
V
9

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
Vying answered 9/12, 2008 at 8:20 Comment(2)
A one liner : echo '{"a":1,"b":2}' | php -r 'echo json_encode(json_decode(fgets(STDIN)), JSON_PRETTY_PRINT)."\n";'Ghirlandaio
Multiline capable: printf '{\n"a":1,\n"b":2\n}' | php -r 'echo json_encode(json_decode(file_get_contents("php://stdin")), JSON_PRETTY_PRINT) . PHP_EOL;'Sola
M
8

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
}
Micrococcus answered 9/12, 2008 at 8:20 Comment(0)
Z
8

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";'
Zachary answered 9/12, 2008 at 8:20 Comment(0)
H
8

There is TidyJSON.

It's C#, so maybe you can get it to compile with Mono, and working on *nix. No guarantees though, sorry.

Hendricks answered 9/12, 2008 at 8:20 Comment(0)
C
7

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}))}}))"
Cheryl answered 9/12, 2008 at 8:20 Comment(0)
F
6

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.

Fancie answered 9/12, 2008 at 8:20 Comment(0)
S
5

You can use Prettier to do this.

npx prettier <JSON file> should print a prettified version of the JSON in the given file, while npx prettier --write <JSON file> will overwrite the given JSON file with prettified JSON.

Sankey answered 9/12, 2008 at 8:20 Comment(1)
this was quite simple & easy to useWheeling
B
5

If you have Node.js installed you can create one on your own with one line of code. Create a file pretty:

> vim pretty

#!/usr/bin/env node

console.log(JSON.stringify(JSON.parse(process.argv[2]), null, 2));

Add execute permission:

> chmod +x pretty

> ./pretty '{"foo": "lorem", "bar": "ipsum"}'

Or if your JSON is in a file:

#!/usr/bin/env node

console.log(JSON.stringify(require("./" + process.argv[2]), null, 2));

> ./pretty file.json

Burwell answered 9/12, 2008 at 8:20 Comment(1)
process.stdin.resume(); var input = ''; process.stdin.on('data', (data) => { input += data; }); process.stdin.on('end', () => { console.log(JSON.stringify(JSON.parse(input), null, 2)); });Burwell
L
5
$ sudo apt-get install edit-json
$ prettify_json myfile.json
Lemaceon answered 9/12, 2008 at 8:20 Comment(0)
G
4

I've came up with this solution: https://calbertts.medium.com/unix-pipelines-with-curl-requests-and-serverless-functions-e21117ae4c65

# this in your bash profile
jsonprettify() {
  curl -Ss -X POST -H "Content-Type: text/plain" --data-binary @- https://jsonprettify.vercel.app/api/server?indent=$@
}
echo '{"prop": true, "key": [1,2]}' | jsonprettify 4
# {
#     "prop": true,
#     "key": [
#         1,
#         2
#     ]
# }

There's no need to install anything, if you have an internet connection and cURL installed, you can use this function.

Are you in another host where you can't install anything, this would be a perfect solution to that issue.

Glum answered 9/12, 2008 at 8:20 Comment(0)
E
4

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
Educable answered 9/12, 2008 at 8:20 Comment(1)
As much as I love Groovy, it isn't a great fit for little scripts like this due to the overhead of the JVM. My informal measurements show jq approximately 50x faster.Ruskin
R
3

https://github.com/aidanmelen/json_pretty_print

from __future__ import unicode_literals
from __future__ import absolute_import
from __future__ import print_function
from __future__ import division

import json
import jsonschema

def _validate(data):
    schema = {"$schema": "http://json-schema.org/draft-04/schema#"}
    try:
        jsonschema.validate(data, schema,
                            format_checker=jsonschema.FormatChecker())
    except jsonschema.exceptions.ValidationError as ve:
        sys.stderr.write("Whoops, the data you provided does not seem to be " \
        "valid JSON.\n{}".format(ve))

def pprint(data, python_obj=False, **kwargs):
    _validate(data)
    kwargs["indent"] = kwargs.get("indent", 4)
    pretty_data = json.dumps(data, **kwargs)
    if python_obj:
        print(pretty_data)
    else:
       repls = (("u'",'"'),
                ("'",'"'),
                ("None",'null'),
                ("True",'true'),
                ("False",'false'))
    print(reduce(lambda a, kv: a.replace(*kv), repls, pretty_data))
Roxyroy answered 9/12, 2008 at 8:20 Comment(0)
A
3
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')".

Antony answered 9/12, 2008 at 8:20 Comment(0)
N
3

Here is a Groovy one-liner:

echo '{"foo": "lorem", "bar": "ipsum"}' | groovy -e 'import groovy.json.*; println JsonOutput.prettyPrint(System.in.text)'
Nephrolith answered 9/12, 2008 at 8:20 Comment(0)
N
3

With JavaScript/Node.js: take a look at the vkBeautify.js plugin, which provides pretty printing for both JSON and XML text.

It's written in plain JavaScript, less than 1.5 KB (minified) and very fast.

Nealey answered 9/12, 2008 at 8:20 Comment(0)
A
3

I'm the author of json-liner. It's a command line tool to turn JSON into a grep friendly format. Give it a try.

$ echo '{"a": 1, "b": 2}' | json-liner
/%a 1
/%b 2
$ echo '["foo", "bar", "baz"]' | json-liner
/@0 foo
/@1 bar
/@2 baz
Alhambra answered 9/12, 2008 at 8:20 Comment(0)
T
2

If you don't mind using a third-party tool, you can simply curl to jsonprettyprint.org. This is for the case where you can't install packages on the machine.

curl -XPOST https://jsonprettyprint.org/api -d '{"user" : 1}'
Tropicalize answered 9/12, 2008 at 8:20 Comment(1)
To pipe stdin to this command, do something like this: echo '{ "foo": "lorem", "bar": "ipsum" }' | curl -XPOST https://jsonprettyprint.org/api -d @-Reservoir
T
1

yq can be used to pretty print JSON

echo '{"foo": "lorem", "bar": "ipsum"}' | yq -o json

It has an option to define the indent

echo '{"foo": "lorem", "bar": "ipsum"}' | yq -o json --indent 3

You can choose between coloured and monochrome output

echo '{"foo": "lorem", "bar": "ipsum"}' | yq -o json --colors
echo '{"foo": "lorem", "bar": "ipsum"}' | yq -o json --no-colors
Tiger answered 9/12, 2008 at 8:20 Comment(0)
E
1

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"
}
Enrica answered 9/12, 2008 at 8:20 Comment(0)
T
1

Also be sure to check out JSONFUI: A command line JSON viewer that supports folding

Tetartohedral answered 9/12, 2008 at 8:20 Comment(0)
C
1

My JSON files were not parsed by any of these methods.

My problem was similar to the post Is Google data source JSON not valid?.

The answer to that post helped me find a solution.

It is considered to be invalid JSON without the string keys.

{id:'name',label:'Name',type:'string'}

must be:

{"id": "name", "label": "Name", "type": "string"}

This link gives a nice comprehensive comparison of some of the different JSON parsers: http://deron.meranda.us/python/comparing_json_modules/basic

Which led me to http://deron.meranda.us/python/demjson/. I think this one parser is much more fault tolerant than many others.

Codding answered 9/12, 2008 at 8:20 Comment(2)
JSON does not allow single quotes as delimiters and a sane JSON parser should reject such input.Stefanistefania
The last two links seem to be broken ("The server at deron.meranda.us is taking too long to respond").Hendricks
J
0

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
Josefjosefa answered 9/12, 2008 at 8:20 Comment(0)
T
0

Agree about jq. You can add the following function to your $HOME/.bashrc:

jqless () {
  args=$1
  shift
  jq --color-output . $args "$@" | less --raw-control-chars
}

This allows an arbitrary number of input JSON files.

Turnip answered 9/12, 2008 at 8:20 Comment(0)
D
0

If you want to visualize json log at console you can use munia-pretty-json

npm install -g munia-pretty-json

Your json data (app-log.json)

{"time":"2021-06-09T02:50:22Z","level":"info","message":"Log for pretty JSON","module":"init","hostip":"192.168.0.138","pid":123}
{"time":"2021-06-09T03:27:43Z","level":"warn","message":"Here is warning message","module":"send-message","hostip":"192.168.0.138","pid":123}

Run the command:

munia-pretty-json app-log.json

Here is readable output on console:

enter image description here

You can format the output with the template. The default template is '{time} {level -c} {message}'

Using template:

munia-pretty-json -t '{module -c} - {level} - {message}' app-log.json

Output:

enter image description here

Dissuasive answered 9/12, 2008 at 8:20 Comment(0)
A
-2

You can also use online tools instead if that is an option for you.

I find http://jsonprettyprint.net to be the simplest and easiest.

Ait answered 9/12, 2008 at 8:20 Comment(0)
N
-3

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
}
Noddy answered 9/12, 2008 at 8:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.