你大概也遇到过这个场景:运维从日志平台导出一个 JSON 文件,1.8GB,丢过来一句话,“帮忙格式化一下,甲方要看”。你深吸一口气,用 VS Code 打开,光标转圈十秒后,整个窗口变灰。切到 Notepad++,直接卡死。最后想起来还有 jq,敲了一行 jq . big.json,内存又飙了七八个 G,机器差点当场罢工。大 JSON 文件的格式化,就是这样一件看起来简单到不值得动脑、数据一上来就变成性能优化题的事情。2026 年再回看这个需求,工具链其实已经稳定了,真正缺的是处理思路。这篇文章我会从底层内存模型说起,把 jq、Node、Python、Go 和流式方案全部过一遍,再给一个 2.1GB 文件的实际处理链路,最后把那些最容易被忽略的坑一次性说完。适合所有需要跟日志导出、数据备份、接口抓包结果打交道的开发、运维和数据同学。
1. 痛点拆解:为什么一个 JSON 文件能卡死你的编辑器
1.1 大家习惯的那些操作,问题出在哪
先说一个反直觉的事:格式化一个 JSON,本身根本不是什么高难度计算。真正的杀手是文件的体积。而几乎所有日常工具,在面对大文件时的处理方式都惊人地一致——一次性把整个文件塞进内存。
VS Code、Notepad++、Sublime 这类编辑器,打开文件时为了支持语法高亮、代码折叠、跳转定位,会把整个文档转化成内部的文档模型。注意,这不是按需加载的延迟解析,而是全量读取并构建,几十 MB 的文件还能扛住,到了几百 MB,内存和 CPU 就会直接被打满。我印象很深的是有一次拿 VS Code 打开一个 400MB 的 JSON,等了两分钟,最后光标能动了,但每次按键都要卡三秒,最后只能用任务管理器强制结束。
在线 JSON 格式化工具更不用说。浏览器要把整个文件读进内存,再转成字符串,再塞给格式化引擎,最后还要渲染到页面上。文件一旦超过几十 MB,页面的加载条基本就是在骗自己。而且把敏感的接口数据、用户日志粘到第三方网站上,本身就是一种数据泄露风险,这一点在 2026 年的今天依然被很多人忽略。
脚本党的常见做法是写一段 Node 或 Python 代码来处理。方向没问题,但如果只是 JSON.parse + JSON.stringify 这种标准写法,问题会更大,因为它比编辑器更纯粹地“全量加载 + 全量重建”。表面上你绕开了图形界面的渲染开销,但实际上内存峰值反而更高。
1.2 格式化背后的内存膨胀模型
为什么这些做法都会卡?原因在于格式化一个超大 JSON 文件时,内存开销不是“文件大小”一份,而是三份叠加。
第一份是原始文本本身。不管你是 readFileSync 还是 open().read(),都会先把文件字节完整放进内存。第二份是解析后生成的对象树。JSON 是嵌套结构,解析器需要为每个对象、数组、字符串、数字分配独立的内存节点。一条 500 字节的 JSON 记录,解析成对象树之后可能占 2KB 到 4KB,整体算下来,一个 500MB 的文件解析树可以膨胀到 2GB 到 3GB。第三份是格式化后的输出文本。缩进、换行、空格会让输出文件比原始文件大 1.5 到 3 倍,而 JSON.stringify(obj, null, 2) 这类函数会把这个输出完整地再生成一份字符串。
所以最终的内存峰值 = 原始文本 + 对象树 + 格式化输出。一个 500MB 的紧凑 JSON,用 Node 的整树方案处理,内存轻松超过 4GB 到 5GB。一台 8GB 的服务器,跑这种脚本基本就是在悬崖边上跳舞。
这也能解释为什么你换一台配置更高的电脑、或者换一个“更轻量”的编辑器,问题依然存在。只要处理模型的根基是“整树加载”,每多一层数据,内存就要翻好几倍。这也是我在后面选择工具时最重要的判断依据:能不能不构建整棵对象树。
1.3 一个被严重低估的事实:格式化之后文件更大
很多人的直觉是“格式化等于整理,整理应该变轻”。但这个直觉用在
