如何在Vim中保存时自动格式化JSON

时间:2014-10-06 10:16:18

标签: json vim format lint

说实话,go已经破坏了我。使用go我已经习惯了我的编辑(vim)强制执行的严格格式标准,并且几乎被团队中和世界各地的其他人接受并遵循。

我想以同样的方式保存JSON文件格式。

问题:如何在vim中保存时自动格式化/缩进/ lint json文件。

10 个答案:

答案 0 :(得分:64)

在一个命令中,试试这个:

execute '%!python -m json.tool' | w  

然后,您可以添加自己的键绑定,使其更简单。当然,要实现这一点,您需要在您的计算机上安装Python。

答案 1 :(得分:30)

如果您热衷于使用外部工具并且正在使用json进行一些工作,我建议您使用jq

https://stedolan.github.io/jq/

然后,您可以在vim中执行:%!jq '.',它将使用jq的输出替换当前缓冲区。

答案 2 :(得分:9)

%!python -m json.tool

%!python -c "import json, sys, collections; print json.dumps(json.load(sys.stdin, object_pairs_hook=collections.OrderedDict), ensure_ascii=False, indent=4)"

你可以将它添加到你的vimrc:

com! FormatJSON %!python -m json.tool

比你可以使用:FormatJson格式的json文件

答案 3 :(得分:8)

感谢mMontu和Jose B,这就是我最终做的事情:

警告这将覆盖您的缓冲区。因此,如果您打开已经存在语法错误的json文件,您将丢失整个文件(或者可能丢失它)。

将此行添加到~/.vimrc

" Ali: to indent json files on save
autocmd FileType json autocmd BufWritePre <buffer> %!python -m json.tool
当然,你需要在你的机器上安装python。

编辑:如果你的json有错误,下一个不应该覆盖你的缓冲区。这使得它成为正确的答案,但由于我没有很好地掌握Vim脚本或shell,所以我把它作为一个实验性的东西,你可以尝试,如果你感到幸运。它也可能取决于你的shell。你被警告了。

" Ali: to indent json files on save
autocmd FileType json autocmd BufWritePre <buffer> %!python -m json.tool 2>/dev/null || echo <buffer>

答案 4 :(得分:4)

在vim.org上搜索JSON插件返回了这个:

jdaddy.vim : JSON manipulation and pretty printing

说明如下:

  

gqaj&#34;漂亮的版画&#34; (换行/缩进/排序键/否则清理)   光标下的JSON构造。

如果它符合您期望的格式,那么您可以在保存时创建autocmd BufWritePre格式。

答案 5 :(得分:3)

Vim Autoformat

https://github.com/Chiel92/vim-autoformat

这个Vim插件支持多种自动格式和缩进方案,以及每种文件类型的自定义格式化程序扩展。

https://github.com/Chiel92/vim-autoformat#default-formatprograms

注意:

您需要安装nodejsjs-beautifyvim-autoformat将这些用作默认外部工具。

npm install -g js-beautify

答案 6 :(得分:1)

这是我的解决方案。它不能完全准确地解决“保存时”的问题部分,但是如果您在保存之前执行此操作,则会输出错误,然后可以在保存前进行修复。

此外,它仅依赖于一个外部工具jq,它已成为unix shell JSON处理工具的黄金标准。以及您可能已经安装了哪些软件(仅限macOS和Linux / Unix; idk在Windows中的行为)

基本上,只是:

ggVG!jq '.'

这将突出显示整个JSON文档,然后通过jq运行它,该语法只是为了正确性而对其进行解析,重新格式化(例如,修复任何缩进等),然后将输出吐回到Vim编辑器中。

如果只想解析文档的一部分,则可以通过按vV手动突出显示该部分,然后运行

!jq '.'

这样做的好处是,您可以通过这种方式修复文档的各个部分。

答案 7 :(得分:1)

另一种解决方案是使用 coc-format-json

答案 8 :(得分:0)

你可以搜索'vim-json-line-format'插件,在Normal mode中打开一个文件,将光标移到json线上,使用<leader>pj通过打印显示格式json,使用<leader>wj可以将文本更改为格式化的json。 无效的json无法格式化!

答案 9 :(得分:0)

我做了一些整理工作(尽管其中一些与vim无关),并且自己在neovim上编写了脚本!

解决方案1:neovim

1-1:自己编写脚本

Neovim允许通过将python文件或软件包放在rplugin/python3/文件夹中的runtimepath中来定义Python3插件)

就我而言

- init.vim
- rplugin/python3/[your_py_file_set].py
- rplugin/python3/fmt_file.py

fmt_file.py如下

# rplugin/python3/fmt_file.py

import pynvim
import json


@pynvim.plugin
class Plugin:
    __slots__ = ('vim',)

    def __init__(self, vim):
        self.vim = vim

    @pynvim.command('FormatJson', nargs='*', range='')
    def format_json(self, args, rg):
        """
        USAGE::

            :FormatJson
        """
        try:
            buf = self.vim.current.buffer
            json_content: str = '\n'.join(buf[:])
            dict_content: dict = json.loads(json_content)
            new_content: str = json.dumps(dict_content, indent=4, sort_keys=True)
            buf[:] = new_content.split('\n')
        except Exception as e:
            self.vim.current.line = str(e)

随后运行:在:UpdateRemotePlugins中运行Nvim一次,以生成必要的Vimscript来使您的插件可用。 (,最好重新启动Neovim

,然后打开要格式化的JSON文件,并在命令中键入::FormatJson。全部完成。


别忘了告诉vim您的Python在哪里

" init.vim

let g:python3_host_prog = '...\python.exe''

pip install pynvim

1-2:使用tool.py

tool.py位于Lib/json/tool.py上的位置

:%!python -m json.tool

solution2:命令行

如果您已经安装了python,则可以打开命令行:

python -m json.tool "test.json" >> "output.json"

solution3:python

我为那些事情写了一个简单的脚本。

"""
USAGE::

    python fmt_file.py fmt-json "C:\test\test.json"
    python fmt_file.py fmt-json "C:\test\test.json"  --out_path="abc.json"
    python fmt_file.py fmt-json "test.json"  --out_path="abc.json"
"""

import click  # pip install click
from click.types import File
import json
from pathlib import Path


@click.group('json')
def gj():
    ...


@gj.command('fmt-json')
@click.argument('file_obj', type=click.File('r', encoding='utf-8'))
@click.option('--out_path', default=None, type=Path, help='output path')
def format_json(file_obj: File, out_path: Path):
    new_content = ''
    with file_obj as f:
        buf_list = [_ for _ in f]
        if buf_list:
            json_content: str = '\n'.join(buf_list)
            dict_content: dict = json.loads(json_content)
            new_content: str = json.dumps(dict_content, indent=4, sort_keys=True)

    if new_content:
        with open(out_path if out_path else Path('./temp.temp_temp.json'),
                  'w', encoding='utf-8') as f:
            f.write(new_content)


def main():
    for register_group in (gj,):
        register_group()


if __name__ == '__main__':
    main()