Given a file with a large JSON object all on one line like
{"versions":[{"count":2,"version":""},{"count":1,"version":"1.1.1"},{"count":14,"version":"2.9"},{...
How can I format this to be human readable in Vim?
Vi and Vim Stack Exchange is a question and answer site for people using the vi and Vim families of text editors. It only takes a minute to sign up.
Sign up to join this communityGiven a file with a large JSON object all on one line like
{"versions":[{"count":2,"version":""},{"count":1,"version":"1.1.1"},{"count":14,"version":"2.9"},{...
How can I format this to be human readable in Vim?
Or you can install jq
which is faster (written in C) from your package manager (e.g. sudo apt install jq
in Ubuntu/Debian, sudo dnf install jq
on Fedora/RHEL/CentOS) or from source and then in vim, type:
:%!jq .
This one-liner works well to format JSON in Vim into a human readable form:
:%!python -m json.tool
:%!jq .
answer these days, as I do less with Python and tend to have jq
installed on my systems for any JSON work in CLI. I also get notifications for this SO question quite often, so it helps me not to forget :P I prefer vim with minimal customization, no plugins, etc, which is another reason the jq
solution is now my preferred.
jq
Jul 20, 2022 at 15:11
To format in a deterministic way, we need to sort the hash. None of the other answers did that for me, so I created my own:
function! FormatJson()
python << EOF
import vim
import json
try:
buf = vim.current.buffer
json_content = '\n'.join(buf[:])
content = json.loads(json_content)
sorted_content = json.dumps(content, indent=4, sort_keys=True)
buf[:] = sorted_content.split('\n')
except Exception, e:
print e
EOF
endfunction
Usage:
:call FormatJson()
jq
mentionned in SebMa answers has a --sort-keys
option which would do the job. But it's cool to write your own implementation too :)
I use this :Jsonf
command. It's can format unicode.
command! Jsonf :execute '%!python -c "import json,sys,collections,re; sys.stdout.write(re.sub(r\"\\\u[0-9a-f]{4}\", lambda m:m.group().decode(\"unicode_escape\").encode(\"utf-8\"),json.dumps(json.load(sys.stdin, object_pairs_hook=collections.OrderedDict), indent=2)))"'
If PHP is available, add the tool jf
as a JSON Formatter by Composer:
$ composer global require codegear/json-formatter
Then Format current file:
:%!jf %
Or add a keymap in vimrc:
nnoremap <Leader>jf :%!jf %<CR>
If nodejs
and xargs
are available on your system you can add the following command to your .vimrc
command! -range FormatJson <line1>,<line2>!xargs -0 -I {} node -e 'console.log(JSON.stringify({}, null, 2));'
After that you can visual select the JSON text in the buffer and run
:'<,'>FormatJson
to pretty print it. Works with Unicode too.
Another solution is to use coc-format-json.
I wanted to open jq with vim. However i didn't manage to find a way to do it in one command.
I wrote a shell script, and it worked for me (linux version : redhat 7.6):
# Don't miss the dot after jq
cat input.json | jq . > output.json
vim output.json
-
to read from stdin: jq input.json . | vim -
(maybe you need to reverse the input.json
and .
in that jq
command). Another option would be to use -c
or +
to run a command when Vim opens: vim +':%!jq .' input.json
May 3, 2021 at 7:41
Use ALE to help you with linting/formatting
Install ALE into .vim/vimfiles/pack/*/opt/ale
add the following line to your vimrc:
packadd ale
if exists("b:my_ftplugin") | finish | endif
let b:my_ftplugin = 1
if !exists('g:loaded_ale') | finish | endif
" Pick from available fixers :help ale-fix
" E.g., use prettier if it is installed:
let b:ale_fixers = ['prettier']
If no fixers are available at your disposal, python is always an option:
if !executable('python') | finish | endif
let b:ale_fixers = [{ -> {'command': 'python -m json.tool --indent 2 -'}}]
:ALEFix
Set all values at a new line with substitute commands (they must fit your file!):
:%s/","/",\r"/g
:%s/null,"/null,\r"/g
:%s/(\d),"/\1,\r"/g
},{
, [{
{
"versions":[
{
"count":2,"version":""
},
{"count":1,
"version":"1.1.1"
},
{
"count":14,
"version":"2.9"
}]
}
Then go to the first {
and type =%.
The JSON will be rudimentary formatted. Not perfect but readable.