拿到一段 JSON,多数人的第一反应是“先格式化一下”。这没错,但格式化只是流程的第一步:它回答“能不能解析”,却回答不了“结构对不对”“和上一版差在哪”“我要的字段在哪一层”。这篇文章用一个订单样本,把格式化、修复、校验、取值、对比、转换串成一条可重复的顺序,并说明每个环节的边界。
先判断你手里的是什么:四类常见输入
不同来源的“JSON”其实是四种东西,处理顺序不同。先分类,能省掉大半排查时间。
| 输入类型 | 典型来源 | 特征 | 第一步用什么 |
|---|---|---|---|
| 严格 JSON | 接口响应、数据库导出 | 双引号、无注释、无尾逗号 | JSON 格式化,直接看树形结构 |
| JSONC / JSON5 | tsconfig、VS Code 设置、手写配置 | 带注释、尾逗号、单引号或裸 key | JSON 修复,输出标准 JSON 再继续 |
| 被污染的文本 | 日志片段、聊天粘贴、从 Python 打印 | 智能引号、True/None、BOM、前后多余文字 | JSON 修复,之后人工核对 |
| 转义后的字符串 | 日志里的 message 字段、嵌套 JSON 字符串 | 整段被引号包住,内部是 \" 序列 | JSON 转义工具先反转义 |
步骤一:格式化,并确认它真的是你以为的那个结构
把内容粘贴到 JSON 格式化页面,输入会在约 300 毫秒后自动格式化,输出区默认是可折叠的树形视图。树形视图里每个节点可以展开、复制或删除,适合先看清层级,再决定下一步。
需要特别知道的一点:本站格式化先尝试标准 JSON 解析,失败后回退到 JSON5 解析,所以带注释和尾逗号的输入也能被“格式化”成功,输出则一定是标准 JSON。好处是省事,代价是它会悄悄放过一部分非法语法。下面用同一份样本演示。
{
// 订单样本
"orderId": "A-1001",
"items": [
{"sku": "kb-01", "price": 349.5, "qty": 1},
{"sku": "ms-02", "price": 129, "qty": 2},
],
"paid": true,
}这份输入用原生 JSON.parse 会失败(注释和两处尾逗号),但格式化页面会成功并输出:
{
"orderId": "A-1001",
"items": [
{
"sku": "kb-01",
"price": 349.5,
"qty": 1
},
{
"sku": "ms-02",
"price": 129,
"qty": 2
}
],
"paid": true
}步骤二:修复,只修“确定性”的问题
JSON 修复页面处理的是有明确规则的问题:删除 // 和 /* */ 注释(字符串内部的不动)、移除对象和数组末尾的逗号、把中文弯引号换成直引号、去掉开头的 BOM,并把 Python 风格的 True / False / None 换成 true / false / null,最后交给解析器格式化为 2 空格缩进的标准 JSON。
它不会替你“猜”:缺失的逗号、被截断的数据、没有闭合的括号、把 undefined 写进去的字段,都不会被自动补全。这是刻意的——猜错的修复比报错更危险,因为你拿到的是一份“看起来正常”的错误数据。遇到这类错误,页面会显示解析器给出的位置信息,需要你回到源头排查。
步骤三:先看形状,再看内容——Schema 生成与校验
当 JSON 来自第三方接口,语法正确并不等于数据可用。字段缺失、类型变了(数字变字符串)、数组里混进 null,都是语法合法但业务出错的典型。流程是:用一份已知良好的样本在 JSON Schema 生成页面生成草稿,修改后再用 JSON Schema 验证页面校验新数据。
上面的订单样本生成的 Schema 会把所有出现的字段标为 required,并把 price 识别为 number、qty 识别为 integer;字符串若符合日期、邮箱或 URL 的常见写法,还会加上 format。需要留意的是:对元素不止一个的数组,生成器会为每个元素各生成一个 schema 并用 oneOf 合并。当两个元素结构完全相同时,oneOf 会在校验时报“匹配了 2 个”,因此生成后要手动把 items 合并成一个 schema,再拿去校验。
验证页面支持 type、required、properties、items、enum、const、minimum / maximum、minLength / maxLength、pattern、minItems / maxItems、additionalProperties、allOf / anyOf / oneOf 以及 email、date、date-time、uri 几种 format,并以路径加原因的形式列出每一处不符。它是一个轻量实现,不是完整规范的校验器,$ref 等高级特性不要指望它覆盖;用于日常排查足够,用于合规性验收请使用你项目里的正式校验库。
步骤四:用 JSONPath 取值,而不是人眼数层级
结构确认后,如果只想要其中几个字段,用 JSONPath 查询页面。对上面的订单:
$.items[*].price → [349.5, 129]
$.items[?(@.price>200)].sku → ["kb-01"]
$.items[*].qty → [1, 2]这比在树形视图里一层层点开更适合深层结构,也方便你把表达式直接带到代码或测试里复用。注意 JSONPath 没有统一的官方实现细节,过滤表达式和脚本表达式在不同库里行为不完全一致,把表达式放进生产代码前,要用你实际使用的库再验证一次。
步骤五:版本对比——看清“这次到底改了什么”
接口升级或配置变更后,用 JSON 对比页面粘贴左右两份内容,结果会按路径列出新增、删除、修改和未变化的条目,并支持隐藏未变化项。比如把订单的 price 从 129 改为 119 并新增 coupon 字段,对比会得到 items[1].price 为 changed、coupon 为 added,一眼定位。
一个关键限制:数组是按下标逐项比较的,不做“智能匹配”。如果新版在数组开头插入了一个元素,后面所有元素都会显示为 changed。需要按 id 对齐的场景,应先在你自己的脚本里按主键排序,再来对比。
步骤六:转换与统计
| 目标 | 使用工具 | 适合 | 注意 |
|---|---|---|---|
| 配置文件互转 | JSON ↔ YAML | K8s、CI 配置 | YAML 的隐式类型(如 yes、no)转换后需复核 |
| 导出给运营 | JSON → CSV / Excel | 同构对象数组 | 嵌套对象需先展平,否则列会很怪 |
| 拍平嵌套 | JSON 展平 / 还原 | 用 a.b.0.c 形式的路径键 | 键名本身含点号时要换分隔符 |
| 写类型定义 | JSON → TypeScript | 前端接口类型草稿 | 只能依据样本推断,可选字段需手改 |
| 评估体量 | JSON 统计 | 深度、键数、类型分布、压缩前后大小 | 仅描述样本,不代表线上平均值 |
常见坑与排查顺序
- 先看第一个字符:以 < 开头几乎一定是 HTML 错误页,不是 JSON 的问题,先查接口状态码和网关。
- 报错位置在行末附近时,多半是缺逗号或前一行引号没闭合,往前看一行。
- 看到 NaN、Infinity:JSON5 回退解析会接受它们,但格式化输出时它们会变成 null。数值信息已经丢了,请回到数据源修正。
- 看到 Windows 路径如 C:\Users:标准 JSON 会因非法转义报错,而 JSON5 回退会把 \U 当成普通的 U,结果变成 CUsers,同时 \b 会变成退格符。路径里的反斜杠要写成 \\。
- 大整数:超过 2 的 53 次方的整数在 JavaScript 里会丢精度(例如 12345678901234567890 会显示为 12345678901234567000)。ID 类字段应当用字符串传输。
- 重复 key:标准解析器不会报错,只保留最后一个。如果怀疑数据被覆盖,要在原文里搜索重复键名。
按场景组合工具:五条常用路径
同一批工具,在不同任务里的顺序并不一样。下面这张表把最常见的五种任务整理成固定路径,每一步都写明了需要确认的内容,这样你不会因为“看起来格式化成功了”就跳过后面的检查。
| 任务 | 推荐顺序 | 每一步要确认什么 |
|---|---|---|
| 联调第三方接口 | 格式化 → Schema 生成 → Schema 验证 | 字段是否齐全、类型是否与对方文档一致、可选字段是否被误标为必填 |
| 排查配置文件的改动 | 修复 → 格式化 → 对比 | 改动是否只落在预期的路径上,有没有被悄悄改写的数值 |
| 给运营同事导出数据 | 格式化 → 展平 → JSON 转 CSV 或 Excel | 列名是否合理,嵌套数组被拍平成多少列 |
| 为前端写接口类型 | 格式化 → JSON 转 TypeScript → 手工修订 | 样本里为 null 或缺失的字段是否应当标为可选 |
| 评估一份很大的响应 | JSON 统计 → JSONPath 抽取关键字段 | 最大嵌套深度、最长字符串、压缩前后体积是否异常 |
所有基于样本的推断(Schema 生成、类型生成)都有同一个局限:样本里没出现的情况不会被覆盖。一个字段在你的样本里恰好总是有值,生成结果就会把它当作必填。因此推断结果应当当作草稿,用第二份、第三份不同的样本去检验,再人工修订。
给团队的四条最小约定
- 在工单或聊天里贴 JSON 样本之前,先格式化并脱敏,让别人不必再自己整理。
- 凡是配置文件,都在文件头或文档中写明“读取它的程序是否支持注释和尾逗号”。
- 接口文档里明确数组的顺序是否有意义;有意义的话,对比时才能按下标比较。
- 约定 ID、金额等对精度敏感的字段用字符串传输,避免大整数和小数在 JavaScript 里丢精度。
什么时候不该用在线(浏览器)工具
- 体量很大的文件(几十 MB 以上):浏览器内存和渲染树形视图都会吃紧,用命令行工具如 jq 更合适。
- 需要在 CI 里自动化校验:浏览器页面无法被脚本调用,应当把 Schema 校验放进你的测试代码。
- 需要完整的 JSON Schema 规范支持或 $ref 解析:使用 Ajv 之类的专业库。
- 需要保留注释的“原地编辑”:格式化和修复的输出是标准 JSON,注释会丢失,不要用它覆盖你的 tsconfig。