商品页面需要显示名称、价格、颜色和是否有货。服务器把这些资料发给手机或网页时,可以用 JSON 把每项信息写清楚,让接收方按字段找到需要的值。JSON 是一种用文本组织和交换数据的格式;它常被选用,是因为规则比较少,能表达有层次的资料,也有很多编程语言支持读取和生成。

把商品资料写成 JSON
假设我们要传递一款帆布包的资料。下面是一份用于解释的 JSON,商品和数值都是示意,价格在这个例子里约定以元计:
{
"name": "帆布包",
"price": 59,
"in_stock": true,
"colors": ["米色", "蓝色"],
"size": {"width_cm": 30, "height_cm": 35},
"discount": null
}
先看 "name": "帆布包"。冒号左边是名字,也常被叫作键或字段名;右边是值。软件按约定知道 name 是商品名称,就能取出“帆布包”,不用从一段商品介绍里猜哪几个字才是名称。
price 对应数字 59,in_stock 对应 true,在本例中表示有货。true、false 这类只有两种状态的值叫布尔值,可以用于表达一个条件是否成立;它们不是带引号的文字。
双引号也帮助软件区分值的类型。59 是数字,"59" 是字符串,也就是一段文本。它们看起来相近,程序读出来的类型却不同,后续计算和比较不能随意混用。JSON 也没有替 59 指定货币单位,这仍然要由使用它的双方约定。
discount 的值是 null,表示这里没有给出具体的折扣值。它为什么为空,究竟是不适用还是暂时未知,还要看接口或业务规则。能读懂格式,不等于已经知道每个字段的业务含义。(参考:ECMA-404[1])
大括号和方括号各管什么
最外层的 { } 把这些有名字的值放在一起,这样的一组数据叫对象。对象适合描述“一件东西有哪些信息”,比如这款包的名称、价格和尺寸。不同字段之间用逗号分开。
colors 后面用的是 [ ],里面按顺序放着“米色”和“蓝色”。这种按顺序排列的一组值叫数组,适合表示颜色选项、商品清单或一组消息。程序读取对象时,要按字段名找到值,不应依赖它恰好排在第几行;数组里的先后顺序则是数据的一部分。
size 的值又是一个对象,里面有 width_cm 和 height_cm。把尺寸的两项信息放到一起,就是嵌套。对象和数组还可以互相包含:例如,一份商品清单可以是一个数组,其中每件商品再用一个对象描述。
JSON 的基本值类型有字符串、数字、布尔值、null、对象和数组。这几种类型加上嵌套,就能表达不少日常资料。名字里的 JavaScript 不意味着只能给 JavaScript 使用;JSON 的全称是 JavaScript Object Notation,它源于这门语言的写法,但本身是独立的数据格式。(参考:JSON 官方介绍[2])

一份数据怎样交到另一个程序手里
程序里原本可能已经有一组商品数据。发送前,它可以把这组数据转换为符合 JSON 规则的文本,这个过程叫序列化。接收方拿到文本后,再解析成自己能访问和处理的数据。JavaScript 有 JSON.stringify() 和 JSON.parse() 完成这类转换,Python 的标准库也提供相应能力;两端不必使用同一种语言。(参考:MDN 的 JSON 说明[3]与 Python JSON 文档[4])
比如,服务器把上面的资料发给网页。网页解析后读到 name 是“帆布包”、price 是 59,再根据页面设计把它们显示成商品名和“¥59”。货币符号、字号、按钮和图片布局由网页决定,并没有自动装在这份 JSON 里。
这里有三件容易混在一起的事:API 约定怎样调用能力,JSON 约定怎样写数据,界面决定怎样呈现结果。 某个网络 API 可以用 JSON 返回资料,也可以采用别的格式。价格计算、库存判断和数据库查询仍要由程序完成。想先理解软件之间怎样调用能力,可以接着看 API 是什么?软件之间是怎么“互相办事”的?。

JSON 自己也不会发送数据。传输要由网络通信等机制完成;它同样可以保存在 .json 文件里,供另一个程序读取。即使一份文件符合 JSON 语法,也不意味着价格就一定正确、字段就一定齐全。接收方还要检查内容是否满足自己的要求。
为什么常用,又为什么不是唯一选择
JSON 兼顾了人查看和程序读取。排好缩进以后,开发者容易看清哪些信息属于同一组;软件可以按固定语法读取,无需理解自然语言。去掉用于排版的空格和换行,前面那份资料仍然可以保持同样的数据含义。(参考:RFC 8259[5])
跨语言支持也是它常用的原因。发送方和接收方可以有不同的内部数据结构,双方只要遵守同一份格式及字段约定,就有办法交换这份资料。JSON 负责这层共同写法,具体的存储、计算和显示仍由各自的软件完成。
规则少,也意味着有明确限制。标准 JSON 的字段名和字符串要用双引号,不允许在最后一个字段后留下多余逗号,也不支持直接写注释。你可能在某些配置文件里见过更宽松的写法,那可能是 JSON5 等扩展格式,或软件自己的扩展,不能默认所有 JSON 解析器都接受。(参考:MDN 的 JSON 与 JavaScript 差异说明[6])
数据交换还有其他选择。一份规整的行列表格,用 CSV 可能更直接;一些系统会选择按预先定义的结构编码数据的 Protocol Buffers。格式选择要看数据形状、两端支持什么,以及传输和维护要求,不能因为 JSON 常见,就说所有场景都该用它。(参考:W3C 表格数据模型[7]与 Protocol Buffers 概览[8])
以后看到一份 JSON,可以先找字段名和对应的值,再看对象、数组怎样包含其他信息。还需要确认字段表示什么、单位是什么、缺少或为空时该怎样处理。这些约定齐了,软件才能把收到的资料用对。
参考资料
- [1] ECMA-404:https://ecma-international.org/publications-and-standards/standards/ecma-404/
- [2] JSON 官方介绍:https://www.json.org/json-en.html
- [3] MDN 的 JSON 说明:https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Scripting/JSON
- [4] Python JSON 文档:https://docs.python.org/3/library/json.html
- [5] RFC 8259:https://www.rfc-editor.org/rfc/rfc8259.html
- [6] MDN 的 JSON 与 JavaScript 差异说明:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON
- [7] W3C 表格数据模型:https://www.w3.org/TR/tabular-data-model/
- [8] Protocol Buffers 概览:https://protobuf.dev/overview/