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

说实话 go把我宠坏了。对于 go,我已经习惯了由我的编辑(vim)强制执行的严格的格式标准,而且几乎被团队中的每个人以及世界各地的每个人所接受和遵循。

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

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

42149 次浏览

在 vim.org 上搜索 JSON 插件可以得到以下结果:

Vim: JSON 操作和漂亮的打印

它的描述如下:

gqaj“漂亮的打印”(包装/缩进/排序键/否则清理) 游标下的 JSON 构造。

如果它的格式化你所期望的,然后你可以创建一个 autocmd BufWritePre格式化时保存。

在一个命令中,尝试这样做:

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

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

感谢 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 没有很好的理解,所以我把它作为一个实验性的东西,如果你觉得幸运的话,你可以尝试一下。这可能也取决于你的壳。我警告你。

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

如果你喜欢使用外部工具,并且正在使用 json,我建议你使用 jq:

Https://stedolan.github.io/jq/

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

Vim 自动格式化

Https://github.com/chiel92/vim-autoformat

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

Https://github.com/chiel92/vim-autoformat#default-formatprograms

注:

您需要安装 nodejsjs-beautify,因为 vim-autoformat使用它们作为默认的外部工具。

npm install -g js-beautify

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

%!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 文件

这是我的解决办法。它没有解决“ on save”的问题部分,但是如果你在保存之前执行这个操作,它会输出错误,你可以在保存之前修复。

此外,它只依赖于一个外部工具—— jq——它已经成为 unix shell JSON 处理工具的黄金标准。并且您可能已经安装了它(仅限于 macOS 和 Linux/Unix; 我想知道这在 Windows 中是如何运行的)

基本上就是:

ggVG!jq '.'

这将突出显示整个 JSON 文档,然后通过 jq运行它,jq将解析它以确保正确性,重新格式化它(例如修复任何缩进,等等) ,并将输出返回到 Vim 编辑器。

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

!jq '.'

这里的好处是,您可以通过这种方式修复文档的小节。

我做了一些组织(尽管其中一些与 vim 无关) ,并自己在 新语言上编写脚本!

解决办法1: 新生语言

1-1: 自己写剧本

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

对我来说

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

然后运行: :UpdateRemotePluginsNvim一次,生成必要的 Vimscript 使您的插件可用。(你最好重启新生语言)

然后,在命令中打开要格式化并键入的 JSON 文件: :FormatJson。好了。


别忘了告诉 Vim 你的蟒蛇在哪

" init.vim


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

pip install pynvim

1-2: 使用 tool.py

tool.pyLib/json/tool.py上的位置

:%!python -m json.tool

解决方案2: 命令行

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

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

解决方案3: 巨蟒

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

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

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

使用 ALE 在保存时自动格式化

配置 ALE 格式化 JSON

. vim/vimfiles/after/ftplugin/json.vim中加入以下内容:

let b:ale_fix_on_save = 1 " Fix files when they are saved.