拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Json格式化全攻略:工具、语言实现与报错排查

Json格式化全攻略:工具、语言实现与报错排查

我最早接触 Json 格式化那会儿,以为就是把一堆挤在一起的字符串“拍扁”,让它能看得清楚就行。后来处理的东西多了才发现,格式化这件事远不止“好看”这么简单。一个被正确格式化、并通过校验的 Json 文件,等于一份自带语法检查、可读性拉满的数据契约;而一个格式乱糟糟的 Json,轻则让你盯半天找不出缺哪个逗号,重则直接把整个服务的请求流程干挂。这篇内容我想从实际使用角度,把 Json 文件格式化的方法、工具、各语言实现,以及各种高频报错的排查思路理顺一遍。

这篇文章适合谁看?后端接口排查报错的人、前端对接数据被嵌套层级绕晕的人、用 Python 分析日志需要清洗 Json 的人、在 Qt/C# 桌面端做配置解析的人,甚至只是想在浏览器阅读器里整理书源 Json、配省市区三级联动数据的人,都能在里面找到能直接抄的段落。提醒一句:如果你搜到的是“u盘格式化”“内存卡无法格式化”“光盘需要格式化”,那咱们说的完全是两码事,这里只讨论纯文本的 Json 文件,不涉及任何磁盘或文件系统层面的格式化。另外,文里不涉及任何代理或网络访问类内容,可以放心看完直接照着操作。

1. 为什么需要格式化 Json,它到底改变了什么

1.1 先想清楚 Json 到底长什么样

Json(JavaScript Object Notation)本质上就是一种基于文本的数据交换格式。它的核心结构其实就两块:对象(用花括号{}包裹的键值对集合)和数组(用方括号[]包裹的有序值列表)。值可以是字符串、数字、布尔值、null、另一个对象或另一个数组。

一段没有格式化的 Json 往往长这样:

{"name":"server-a","status":"running","metrics":{"cpu":12.5,"mem":0.83},"tags":["prod","primary"]}

这不是不能看,但一旦字段多起来,嵌套深起来,这种“压缩形态”就非常折磨人。经过格式化之后,它变成:

{ "name": "server-a", "status": "running", "metrics": { "cpu": 12.5, "mem": 0.83 }, "tags": ["prod", "primary"] }

这种用缩进、换行把层级关系表达出来的过程,就是 Json 格式化。工具干的事情本质上只有两件:先把原始文本解析成内存里的结构化数据对象,再把这个对象按照缩进规则重新序列化输出。所以真正的格式化工具一定会顺带做一次语法校验——能格式化成功,说明这段 Json 至少在语法上是合法的;格式化报错,说明文本里有语法问题,比如缺引号、多逗号、括号不配对。

1.2 格式化解决的三个真实问题

第一个问题是排查问题。接口报错时你拿到一段被日志系统截断的响应体,字符挤在一起根本看不出哪一段出了问题。格式化之后,层级关系清晰,哪个字段缺失、哪条字符串没闭合,一眼就能锁定方向。

第二个问题是数据审查和交接。我做数据对接时经常收到同事甩过来的省市区三级联动 Json,还有各种书源、音乐源配置,它们通常是从某处复制粘贴出来的压缩文本。直接肉眼核对嵌套层级几乎不可能,先格式化再审查是最基本的动作。把字段对整齐之后,只要层级和业务文档对得上,数据基本不会有大问题。

第三个问题是调试和演示。写技术文章、做接口文档示例、给非技术同事讲解数据结构时,一段格式化好的 Json 比一段压缩文本专业得多,也更容易让人理解每个字段的含义。顺带说一句:服务端实际传输时并不需要格式化,线上接口为了省带宽往往用压缩形态,格式化只是给“人”看的,机器不在乎换行和缩进。

2. 选择合适的格式化工具:在线、离线与编辑器插件

2.1 在线工具怎么选,敏感数据要注意

在线 Json 格式化工具是最省事的方案,比如常见的 Json.cn、BeJson 这类站点,打开网页把内容粘进去,一键就能得到格式化结果,有的还带校验、转义、压缩等功能。对于偶尔处理一次 Json 的人来说,在线工具完全够用。

但这里要特别提醒一句:千万别把敏感数据直接贴到在线工具里。我见过有人把线上环境的配置项、带内部信息的接口响应体直接复制到网页里格式化,这等于把数据交给第三方服务。涉及密钥、token、个人信息的内容,一律不要用在线工具。如果你只是格式化一段示例数据或者确认一个语法问题,在线工具没问题;如果是公司内部数据,请使用本地工具或命令行方案。

2.2 离线工具与命令行方案,内网隔离环境必备

很多办公环境有安全要求,不能访问外网,这时候离线工具就是刚需。最简单的离线方案其实不用装任何软件:只要电脑上有 Python,一行命令就能格式化。Python 自带的json.tool模块就是一个小巧的格式化器:

# 从文件读取并格式化输出 python -m json.tool input.json # 把格式化结果写回文件 python -m json.tool input.json output.json

命令行工具还有一个好处,就是可以放进脚本里批量处理。如果你在 Linux 服务器上工作,jq是更强大的选择:

# 格式化并带上颜色高亮 jq . input.json # 格式化后写回文件 jq . input.json > output.json

jq不只是格式化,还能做查询、过滤、重组数据,是处理 Json 的瑞士军刀。Windows 环境下不想装 Python 也不想装 jq,可以下载一个绿色版的“Json 格式化工具离线版”,一般就是单文件 exe,双击打开把内容粘进去就能用,不联网也能正常工作。还有一些人用 Notepad++ 加 JSON Viewer 插件来实现格式化,上面热词里提到的“nodepad怎么格式化json”就是这个思路,装好插件后按快捷键即可。

2.3 编辑器插件与快捷键,日常开发首选

如果你每天都要跟 Json 打交道,我强烈建议直接使用编辑器的内置功能或插件,不要每次都开网页。

VS Code 的操作很简单:打开一个.json后缀的文件,右键选择“格式化文档”,或者直接按Shift + Alt + F,瞬间完成格式化。如果你希望保存时自动格式化,可以在设置里打开Format On Save。这个配置本身也是写在settings.json里的,改起来很方便。很多人会把“vscode 自动格式化代码在哪关闭”这个问题的答案忘了,就是在这个设置项的开关上。

IDEA 家族(IntelliJ IDEA、PyCharm、WebStorm)都有内置的 Format 功能,选中 Json 内容后按Ctrl + Alt + L可以格式化。对于纯 Json 文件,用它的内置 JSON 插件就能完成校验和格式化。如果你经常需要把 Json 转成类、或者从 Json 生成数据结构,可以装一个 Json Parser 插件,功能更全。

这里必须纠正一个很容易踩的误区:热词里有个“vscode使用clangformat格式化”,很多人以为这个插件可以格式化 Json。实际上clang-format是 C/C++ 代码格式化工具,它不负责 Json 格式化,而是负责.cpp、.h这类代码文件的风格整理。VS Code 里处理 Json 用内置的格式化器就行,不需要也不应该用 clang-format 去格式化数据文件。

无论用什么编辑器,团队协作时都应该约定统一的格式规范:缩进用 2 个空格还是 4 个空格、结尾是否加换行、utf-8 编码不带 BOM。这些规则应该固化到.editorconfig或者.vscode/settings.json里,提交到代码仓库,让所有成员共享。否则你格式化成 4 空格、同事格式化成 2 空格,每次提交都产生一大堆 diff,代码评审就没法看了。

3. 常用编程语言里如何格式化 Json 输出

3.1 Python 环境下的格式化实操

Python 是做数据清洗和接口调试最方便的语言,格式化 Json 也最简单。核心方法是json.dumps(),它有几个关键参数几乎每次都要用到:

import json data = { "name": "order-service", "env": "prod", "limit": 100, "tags": ["payment", "core"], "extra": {"timeout": 30} } # indent=2 表示缩进2个空格,ensure_ascii=False 让中文原样显示 formatted = json.dumps(data, ensure_ascii=False, indent=2) print(formatted)

输出效果:

{ "name": "order-service", "env": "prod", "limit": 100, "tags": [ "payment", "core" ], "extra": { "timeout": 30 } }

注意那个ensure_ascii=False。默认情况下 Python 会把所有非 ASCII 字符转成\uXXXX这种转义形式,比如“支付”会变成"\u652f\u4ed8"。这在某些场景下是必须的(比如为了兼容只认 ASCII 的老旧系统),但绝大多数场景下,我们希望在日志和配置文件里直接看到中文原文,所以一定要把ensure_ascii设成False。

还有一个高频需求:读取一个已经存在的 Json 文件,格式化以后再写回去。完整代码如下:

import json from pathlib import Path def format_json_file(input_path: str, output_path: str = None): src = Path(input_path) dst = Path(output_path) if output_path else src with src.open("r", encoding="utf-8") as f: # 这一步会做完整的语法校验,失败时抛出 json.JSONDecodeError obj = json.load(f) with dst.open("w", encoding="utf-8", newline="\n") as f: json.dump(obj, f, ensure_ascii=False, indent=2) f.write("\n") if __name__ == "__main__": format_json_file("config.json")

这个脚本里的几个细节值得说:encoding="utf-8"保证中文文件正常读写;newline="\n"防止在 Windows 下写出\r\n换行符,保证跨平台 diff 一致;最后手动补一个换行,符合 Linux 下文本文件以换行结尾的惯例。这个脚本我已经往工程里复制了无数次,属于那种“抄作业直接能跑”的工具。

3.2 JavaScript 与 Node.js 的格式化方式

前端和 Node.js 环境处理 Json 就更直接了,JSON.stringify天生支持格式化:

const obj = { name: "api-gateway", replicas: 3, endpoints: ["/v1/order", "/v1/user"], deploy: { region: "cn-east", canary: true } }; // 第二个参数是替换函数(一般传 null),第三个参数是缩进空格数 console.log(JSON.stringify(obj, null, 2));

输出效果和 Python 类似,缩进空格数可以自由控制。JSON.stringify(obj, null, "\t")还能用 Tab 缩进,但不推荐混用 Tab 和空格,格式规范要统一。

Node.js 里读取并格式化一个 Json 文件,最朴素的写法是:

const fs = require("fs"); const raw = fs.readFileSync("input.json", "utf-8"); const obj = JSON.parse(raw); // 解析失败直接抛异常 const formatted = JSON.stringify(obj, null, 2); fs.writeFileSync("output.json", formatted + "\n", "utf-8");

对于很大的 Json 文件,JSON.parse在同一线程里会阻塞事件循环,导致 Node 服务出现卡顿。如果你要处理几十 MB 甚至上百 MB 的 Json,建议拆成流式解析,或者干脆丢给 Python/命令行工具处理。大多数场景用不上这个复杂度,但心里有这个概念能帮你避开一个隐藏的大坑。

3.3 Java 与 C# 的格式化输出

Java 世界里最常用的 Json 库无非 Jackson 和 Gson。用 Jackson 格式化输出如下:

import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; ObjectMapper mapper = new ObjectMapper(); mapper.enable(SerializationFeature.INDENT_OUTPUT); Object data = mapper.readValue(jsonStr, Object.class); String prettyJson = mapper.writerWithDefaultPrettyPrinter() .writeValueAsString(data);

如果是从零构造对象再输出,直接用writerWithDefaultPrettyPrinter()就能在序列化时自动加上缩进。Gson 也有对应的简洁写法:

import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonParser; String prettyJson = new GsonBuilder().setPrettyPrinting() .create() .toJson(JsonParser.parseString(jsonStr));

这两种写法看起来简单,但它们在底层做的事情完全一致:先把 Json 字符串解析成内存中的数据结构,再按 pretty 模式重新序列化。所以我前面说“格式化自带校验”,在 Java 这里体现得很明显——如果原始字符串语法有问题,JsonParser.parseString()或者其他 readValue 都会直接抛异常。

C#/.NET 里格式化 Json 同样常见。升级到 .NET Core 3.0 之后,官方推荐用System.Text.Json:

using System.Text.Json; var obj = JsonSerializer.Deserialize<JsonElement>(jsonStr); var formatted = JsonSerializer.Serialize(obj, new JsonSerializerOptions { WriteIndented = true });

老项目还在用 Newtonsoft.Json 的话,就用JToken:

using Newtonsoft.Json; using Newtonsoft.Json.Linq; var json = JToken.Parse(jsonStr); string formatted = json.ToString(Formatting.Indented);

这里插一句:热词里有个“C# timespan格式化”,很多人搜索时可能把这俩混在一起了。TimeSpan格式化是把时间间隔转成hh:mm:ss这样的字符串,它跟 Json 完全是两个话题,只是恰好都叫“格式化”而已。如果在 Json 配置里需要表示时长,我一般推荐直接用整数秒或者 ISO 8601 字符串,不要自己搞自定义格式,不然序列化反序列化时容易对不上。

3.4 C++/Qt 环境处理 Json

嵌入式或客户端开发里,Qt 的QJsonDocument是高频工具。从 Json 字符串格式化输出的方式是:

#include <QJsonDocument> #include <QJsonObject> #include <QFile> #include <QTextStream> QByteArray readFile(const QString &path) { QFile file(path); if (!file.open(QIODevice::ReadOnly)) return {}; return file.readAll(); } void writePrettyJson(const QString &inputPath, const QString &outputPath) { QJsonParseError err; auto doc = QJsonDocument::fromJson(readFile(inputPath), &err); if (err.error != QJsonParseError::NoError) { qWarning() << "parse error:" << err.errorString(); return; } // Indented 模式输出带缩进的 Json,Compact 模式输出压缩形态 QFile out(outputPath); if (out.open(QIODevice::WriteOnly)) { out.write(doc.toJson(QJsonDocument::Indented)); } }

QJsonDocument::fromJson()的第二个参数QJsonParseError很重要,它能告诉你解析失败的具体位置和原因。我写 Qt 程序时,凡是读取配置文件的地方,都会把这个错误信息打进日志,这样用户反馈配置有问题时,我能直接从日志里看到是哪一行哪一列出了问题。热词里提到“qt json struct”和“qt读写json”,基本就是这样的操作:读入QJsonDocument,按字段取出值赋给结构体,写回时再序列化。要注意 Qt 自带的toJson(Indented)默认使用 2 个空格缩进,跟 Python、JS 的默认行为一致,跨语言对齐时基本不用额外处理。

Go 语言里则是json.MarshalIndent(data, "", " "),两个空格是社区主流习惯。核心思路都一样:先 parse,再 serialize,中间多做一次语法校验。各种语言的格式化方式可以汇总成下面这张表,方便你快速对照查:

语言/环境核心方法或命令缩进参数备注
Pythonjson.dumps(obj, ensure_ascii=False, indent=2)indentjson.tool可直接命令行格式化
JavaScript/NodeJSON.stringify(obj, null, 2)第三参数为空格数大文件避免同步 parse
Java (Jackson)writerWithDefaultPrettyPrinter().writeValueAsString(obj)默认2空格解析失败会抛异常
Java (Gson)new GsonBuilder().setPrettyPrinting().create()默认2空格可链式调用
C# (System.Text.Json)JsonSerializer.Serialize(obj, options)WriteIndented = true
C# (Newtonsoft)JToken.Parse(str).ToString(Formatting.Indented)默认缩进
C++/Qtdoc.toJson(QJsonDocument::Indented)默认2空格解析时注意QJsonParseError
Gojson.MarshalIndent(v, "", " ")prefix/indent
命令行python -m json.tool in.json/jq . in.json可脚本化,建议内网环境使用

4. 格式化之后的检查:校验、Schema 与前后端联调

4.1 格式化成功不等于数据合法

很多人格式化完就觉得万事大吉,这是个非常危险的误解。格式化只保证语法层面没问题,也就是说括号配对、引号闭合、字段名有双引号,这些基础语法是对的;但格式化不保证业务层面正确,比如该有的字段有吗、类型对吗、枚举值合法吗,这些格式化工具完全看不出来。

举个例子,一段请求体{"user_id": "123", "amount": "abc"},格式化非常顺利,大概率也没有任何一个 JSON 解析器会报错,因为字符串"abc"本身是合法的 Json 值。但如果你把这段发给后端接口,后端期望amount是数字类型,就会在反序列化阶段报错。这种错误用格式化工具是定位不了的,需要靠类型校验和字段校验来做。

所以在实际工程里,我给自己定的原则是:格式化只是第一步,校验才是目的。手动审查辅以 Schema 定义,才是可靠的思路。

4.2 字段缺失类报错的定位思路

热词里出现频率很高的一个报错是:

failed to deserialize the json body into the target type: input: missing fie

这句话虽然看着吓人,但拆开后就很容易理解:服务端要把 Json 反序列化成预期的数据结构,结果没找到某个字段,于是反序列化失败。注意它说的是missing fie,很可能是错误消息被截断了,真实内容大概率是missing field "xxx"。

这种问题怎么定位?步骤可以固定下来:

  1. 拿到接口请求的原始 Json 文本,先格式化,确认能正常解析。
  2. 打开后端服务定义的 DTO/实体类,逐个字段和 Json 字段对照,找出哪些字段在请求体里不存在。
  3. 确认字段名是否一致。前端常用 camelCase(userId),后端如果定义成 snake_case(user_id),字段名就对不上。
  4. 确认字段类型是否匹配。Json 里传了"123"字符串,而后端期望int,同样会导致反序列化失败。

我在一次真实的联调里遇到过类似情况:前端把"is_active": 1传了过来,后端定义的是bool is_active,结果 Json 解析器直接把 1 解析成布尔时失败。这类问题格式化工具看不出任何异常,因为语法完全合法。后来我们在团队里强制约定:接口文档必须标注每个字段的类型和可空性,前后端各拿一份,联调之前先对一遍字段清单。

4.3 大模型 Json 输出与 Schema 校验的实战

最近的热词里涉及到“大模型json schema报错”和“model query failed: 400: failed to deserialize the json body into the target”,这些看起来很新的问题,本质上还是 Json 格式和 Schema 校验的老问题,只是换了个场景。

大模型在生成结构化输出时,经常因为格式不稳定导致下游解析失败。比如你要模型返回一个对象数组,结果它给你补了一句“好的,以下是结果:”,再输出 Json,这就在 Json 前面多了非 Json 内容,直接解析失败。又或者模型输出过程中字符串被截断,出现unterminated string,JSON 解析器同样报错。

解决思路有这么几个:

  • 调接口时要求返回严格 Json,设置response_format之类的参数为json_object,让服务端尽量约束模型输出。
  • 拿到响应后先做一次预处理,把代码块标签(比如json 和)去掉,再尝试格式化解析。
  • 配合 Json Schema 做字段级校验,确认模型返回的内容结构符合预期。热词里面提到的“gpt跳验证码加json解决”,本质上也是用 Json 格式约束请求和响应的可预期性,规避解析和校验的不确定性。

这类问题的排查手段和传统接口联调没有区别:先把原始文本保存下来,格式化看结构,再对照预期的 Schema 找差异。不格式化,直接盯着几千个字符找问题是毫无效率可言的。

4.4 中文、转义、浮点精度的几个细节

处理 Json 格式化时,有三个细节最容易出问题,这里单独拎出来说。

中文显示问题。Python 默认会把中文转成\uXXXX,Java 的某些库也有类似行为,JavaScript 的JSON.stringify不会转中文,原样输出。如果你在 Python 环境里看到一坨\u开头的东西,一定记得加ensure_ascii=False。配置文件、日志、接口文档里,中文以可读形式存在永远比转义形式友好。

转义问题。Json 字符串内部的引号和反斜杠必须转义,比如内容里有双引号时,序列化后变成\";有换行符时,序列化后变成\n。如果你手动拼 Json 而不是用序列化器,很容易写出不合法的转义序列。所有正规语言库都会自动处理转义,所以我的建议始终是:不要手拼 Json 字符串,永远先构造对象再序列化。

浮点精度问题。Json 传输浮点数时,某些高精度场景下会丢失精度。比如你在 Python 里有一个Decimal("0.1"),直接序列化成 Json 可能变成 0.1,看起来没问题,但某些情况下数字会被转换成科学计数法或者丢失尾数。用 Json Schema 校验数字范围时也会遇到边界值问题。这类问题没有统一解法,只能在业务层约定好精度、用字符串承载大数,或者用allow_nan=False一类参数把非法浮点值拦截在序列化阶段。

5. 高频报错与排查思路速查

5.1 常见 Json 报错速查表

我把实际工作中遇到的高频 Json 报错整理成了一张表,遇到问题可以先查表,再决定下一步怎么处理。

报错信息常见原因排查思路
Expecting property name enclosed in double quotes字段名没加双引号,或使用了单引号格式化原始文本,找到出错位置,给字段名补双引号
Expecting ':' delimiter键值之间缺冒号,或前一个值后面多逗号查看分隔符是否正确,尤其是多行手写配置时
Unterminated string in json at position 8192字符串被截断,或引号没有闭合看是不是日志/网关对单条内容有长度限制,检查原始数据完整性
Unexpected end of JSON inputJson 内容不完整,缺括号或数组缺元素确认内容是否被截断,补全括号
Failed to deserialize the json body into the target type: missing field请求体字段缺失,或字段名不匹配对照后端 DTO 字段清单,逐字段核对
400: model query failed大模型接口请求体结构错误或超限检查是否有多余字段、类型是否正确、内容长度是否超限
JSON 解析成功但业务校验失败字段存在但值类型不对,或枚举值不合法用 Schema 或文档校验字段类型和取值范围

这张表里最容易被忽视的是Unterminated string,因为它经常不是 Json 本身写错了,而是数据在传输、存储过程中被截断了。位置 8192 这个数字很有代表性,很多系统单次消息体超过 8KB 就会被截断,所以看到 position 比较大的报错时,第一反应应该是“内容完整吗”,而不是“语法错在哪”。

5.2 从一次真实线上问题看定位流程

去年我处理过一次典型的 Json 格式化排查,当时服务 A 调用服务 B 的接口,返回 500。查 B 服务日志,发现只有一行反序列化错误:input: missing field "items"。这行错误出来之后,我们并不知道请求体里到底缺了什么,于是先让 A 服务把实际发出的请求体打到日志文件里。

拿到原始请求体之后,第一件事就是格式化。格式化顺利完成说明语法没问题,但读起来发现items这个字段确实不在请求体里,而且页面展示的productList倒是有一个。最后定位到根因是 A 服务代码里对象名和数据字段对不上的映射错误,改一行配置就好了。

整个过程耗时大概半小时,其中至少有二十分钟是花在“等 A 服务重新打日志”和“格式化原始文本”上。如果 A 服务从一开始就在日志里把 Json 格式化输出,我们定位的时间至少能压缩一半。所以我后来特别强调:服务里所有打印请求体、响应体的地方,统一用缩进格式输出,并且控制单条日志大小,避免被日志框架截断。

5.3 避免踩坑的三条经验

第一,生产环境打印 Json 日志要克制。格式化输出虽然可读,但会显著增加日志体积。你不可能让线上每个接口打印完整请求体,否则日志量和存储成本都扛不住。我的做法是:调试级别打印完整格式化 Json,生产级别只打印业务关键字段和错误信息。

第二,团队统一格式配置要落地到仓库。.editorconfig和.vscode/settings.json不只是给编辑器用的,它代表团队的代码规范。如果不统一,你格式化一次,同事再格式化一次,每次提交都在制造噪音 diff,时间长了大家都不敢碰配置文件了。

第三,写文件时始终保留一个换行符在末尾。很多命令行工具和编辑器对“文件最后是否有换行”非常敏感,Python 的json.dump默认不写末尾换行,所以我习惯在写完后再补一个"\n"。这个细节看起来不起眼,但对 CI 检查和 Git diff 的整洁度影响很大。

6. 一个顺手就能用的小脚本:批量格式化目录下的 Json 文件

如果手头有一堆 Json 文件需要处理,比如一个项目里有几十个配置文件,或者从某处下载了一批书源 Json、区域数据 Json,手动一个个格式化显然不现实。这里分享一个我常用的 Python 批处理脚本,它做的事很简单:递归遍历目录、备份原文件、格式化 Json、识别解析失败的文件,最后输出统计结果。

import json from pathlib import Path def format_dir(root: str, suffix: str = ".json", backup: bool = True): base = Path(root) ok_count = 0 fail_list = [] for src in base.rglob(f"*{suffix}"): try: with src.open("r", encoding="utf-8") as f: obj = json.load(f) if backup: bak = src.with_suffix(src.suffix + ".bak") bak.write_text(src.read_text(encoding="utf-8"), encoding="utf-8") with src.open("w", encoding="utf-8", newline="\n") as f: json.dump(obj, f, ensure_ascii=False, indent=2) f.write("\n") ok_count += 1 print(f"[OK] {src}") except Exception as e: fail_list.append((str(src), str(e))) print(f"[FAIL] {src}: {e}") print(f"\n格式化完成:成功 {ok_count} 个,失败 {len(fail_list)} 个") for path, err in fail_list: print(f" - {path}: {err}") if __name__ == "__main__": format_dir("./configs")

脚本里加了backup参数,默认在格式化前生成.json.bak备份文件。这是我在处理大批量配置文件时养成的习惯:格式化是不可逆的(至少对缩进风格来说),万一某个文件解析失败或者格式化后业务读取异常,还能从备份里快速还原,不用去翻版本控制历史。

用这个脚本处理过几十个省市区三级联动数据之后,我最大的感触是:格式化工具本身不复杂,但可靠的备份机制和清晰的错误输出才是真正节省时间的地方。脚本的逻辑很简单,按需调整就行。

7. 再聊几句实在的

做 Json 格式化这件事,真正考验人的往往不是某个工具不会用,而是遇到报错时有没有一套稳定的排查思路。先把原始内容保存下来,再格式化,再对照 Schema 或字段清单找差异,这套流程我用了很多年,几乎能覆盖所有 Json 相关的问题。格式化不是目的,能通过格式化确认数据结构和预期一致,才是背后真正的价值。希望这篇文章里的方法、脚本和踩坑记录能帮你少走一些弯路。

返回列表