📋 JSON 入门指南:从零开始理解 JSON 数据格式
作者:kaenfsk · 发布于 2026 年 8 月 · 阅读约 8 分钟 · 最后复核 2026 年 10 月 12 日 · 内容与维护标准
为什么 JSON 值得深入理解
JSON(JavaScript Object Notation)是现代 Web 开发中绕不开的基础格式。它最初由 Douglas Crockford 在 2001 年提出,如今已经成为 RESTful API、微服务通信、配置文件、日志结构化输出的事实标准。根据许多公开的 API 目录统计,超过 90% 的公共 Web API 都以 JSON 作为默认返回格式。
对开发者而言,理解 JSON 不只是"会写花括号",而是要知道它在不同语言、不同场景下的行为差异。很多隐蔽的线上问题——接口返回突然解析失败、数据精度丢失、中文乱码、超大 JSON 导致页面卡死——根源都在于对 JSON 的某些细节理解不足。这篇文章会从语法、实践、性能、排查四个维度展开,帮助你真正用好 JSON。
第一部分:JSON 语法速览与容易踩的坑
六种数据类型
- 对象(Object) — 花括号包裹的键值对集合,键必须为字符串
- 数组(Array) — 方括号包裹的有序值列表,可以嵌套任意类型
- 字符串(String) — 双引号包裹,支持 Unicode 和转义字符
- 数字(Number) — 整数或浮点数,JSON 规范不区分整数与浮点
- 布尔值(Boolean) — true 或 false
- null — 表示空值,注意它不是 0,也不是空字符串
这套类型系统看起来简单,但实际使用中经常出问题。最典型的几个坑:
- 键名必须双引号 — JavaScript 对象允许
{name: "张三"},但 JSON 必须写成{"name": "张三"},单引号或裸键名都会导致解析失败 - 末尾不能有逗号 —
{"a": 1,}是无效 JSON,这个错误在人工编辑配置时尤其常见 - 不支持注释 — 标准 JSON 不允许
//或/* */注释。很多开发者会在 package.json 里写注释然后发现 npm 报错 - 数字精度 — JSON 规范没有规定数字精度,但 JavaScript 的 Number 是 64 位浮点数,超过
Number.MAX_SAFE_INTEGER(9007199254740991)的大整数会丢失精度。数据库中常见的 BIGINT 主键、雪花算法 ID 都可能踩这个坑 - 区分 null 和字段缺失 —
{"name": null}和{}语义不同:前者表示"显式置空",后者表示"字段不存在"。很多接口联调问题源于对这两种状态的混淆
第二部分:一个真实案例——API 调试中的 JSON 排查
假设你在对接一个订单查询接口,返回内容长这样:
{"code":0,"data":{"orderId":1574986233000123456,"amount":99.90,"items":[{"sku":"A1001","count":2}],"remark":null}}前端拿到后直接展示,却发现 orderId 显示成了 1574986233000123000。问题就出在数字精度:orderId 是雪花算法生成的 19 位整数,超出了 JavaScript 的安全整数范围。解决方案有两种:一是后端在序列化时将大整数转为字符串,二是前端使用支持 BigInt 的解析库并自行处理。
再看一个更隐蔽的问题。某次接口偶尔报"JSON 解析失败",但复现时数据看起来正常。后来发现是网关层在某些情况下给响应加了 BOM 头(Byte Order Mark),或者压缩层返回了空字符串。排查这类问题的方法是:在解析前打印原始字符串的长度和前几个字符的 charCode,而不是直接看控制台输出——控制台会隐藏不可见字符。
第三个常见场景是中文乱码。后端用 GBK 编码返回了 JSON,但前端按 UTF-8 解析,结果中文字符全部变成乱码。正确的做法是在请求头里明确 Accept-Charset 或统一让后端返回 UTF-8,而不是在前端做转码补救。
第三部分:JSON 在前端的正确用法
JSON.parse 的第二个参数与安全
大多数开发者只用到 JSON.parse(str),但 JSON.parse(str, reviver) 的第二个参数 reviver 在处理日期字符串、特殊字段转换时非常有用。例如把 API 返回的 "2026-08-31T12:00:00Z" 自动转为 Date 对象:
const data = JSON.parse(json, (key, value) => {
if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T/.test(value)) {
return new Date(value);
}
return value;
});安全性方面,永远不要用 eval() 来解析 JSON,也不要直接信任来自外部的 JSON 数据。虽然 JSON 语法上不能执行任意代码,但解析超大或深度嵌套的数据仍可能导致浏览器卡顿,必要时应该做大小和深度限制。
JSON.stringify 的参数
JSON.stringify(obj, replacer, space) 的第三个参数 space 用于缩进格式化,第二个参数 replacer 可以过滤或转换字段。在调试时用 JSON.stringify(obj, null, 2) 输出格式化结果非常实用;在传给后端时,应该用 JSON.stringify(obj) 输出压缩格式,减少传输体积。
还有一个实用技巧:用 replacer 处理 undefined 和函数。默认情况下 JSON.stringify 会跳过值为 undefined 的键,这有时会导致接口参数缺失。如果希望显式报错或转成 null,可以通过 replacer 控制。
第四部分:后端与数据库中的 JSON
后端处理 JSON 时,最需要关注的是序列化一致性。同一个对象,在不同语言中序列化结果可能不同:Go 的 time.Time 默认序列化为 RFC3339 字符串,Java 的 LocalDateTime 如果没有配置 Jackson 会序列化为数组,Python 的 datetime 则直接报错。团队里应该约定统一的日期时间格式(推荐 ISO 8601 + UTC),并在 API 文档中写清楚。
数据库方面,MySQL 的 JSON 类型、PostgreSQL 的 jsonb、MongoDB 的 BSON 都支持在数据库层面操作 JSON。PostgreSQL 的 jsonb 支持 GIN 索引,可以在 JSON 字段上高效查询;MySQL 的 JSON 类型则可以在虚拟列上建索引。需要注意的是,JSON 字段并不适合作为所有场景的万能方案——结构清晰、查询频繁的数据还是应该设计成规范的表结构。
第五部分:性能与容量优化
- 传输优化 — 去除 JSON 中不必要的空格和换行,压缩率通常可以提升 30% 以上;配合 HTTP 的 gzip/brotli 压缩,收益更明显
- 字段瘦身 — 检查接口返回的 JSON 是否包含前端不需要的字段,减少冗余可以降低解析时间和内存占用
- 增量更新 — 对于频繁轮询的接口,考虑使用 JSON Patch(RFC 6902)只传输变更部分,而不是每次返回全量数据
- 分页与流式 — 超大列表一定要分页;如果必须传输大 JSON,可以考虑 NDJSON(每行一个 JSON 对象)实现流式解析
第六部分:常见问题速查
Q: JSON 和 JavaScript 对象是一回事吗?
不是。JSON 是纯文本格式,键必须双引号、不支持函数和注释;JavaScript 对象是内存中的数据结构。二者可以通过 JSON.parse 和 JSON.stringify 互相转换。
Q: 为什么我改了 JSON 配置但程序没生效?
检查三处:文件是否真的保存成功、程序是否缓存了旧配置、JSON 是否有隐藏的 BOM 或非法字符。用编辑器右下角的编码信息确认文件是 UTF-8 无 BOM。
Q: 大整数精度丢失怎么解决?
后端把大整数序列化为字符串,前端用字符串展示或配合 BigInt 处理。不要在序列化阶段丢失精度后再想办法补救。
Q: 如何快速格式化校验 JSON?
使用本站的 JSON 格式化/校验工具,粘贴后自动校验语法并定位错误,支持格式化和压缩两种输出。
总结
JSON 看似简单,但真正用好它需要在语法细节、跨语言行为、性能优化和问题排查几个层面都建立清晰的认识。希望这篇实战指南能帮你少踩一些坑。如果你有其他 JSON 相关的实战经验,欢迎通过 联系我们 页面分享。