FlowingDev

JSON 解析:互联网最爱的数据格式

学习 JSON (JavaScript Object Notation) 的基础知识,这种轻量级的数据交换格式是现代 Web API 和应用程序的动力源泉。

试用工具: JSON 查看器

一句话概括

JSON 是一种基于文本的方式,可以像列表或字典一样组织数据,让计算机和人类都能极其轻松地读取、编写和交换信息。

它解决的问题

想象一下 21 世纪初的互联网。如果你想让你的网页在不重新加载整个页面的情况下获取新数据(一个叫做 AJAX 的热门新概念),你可能得跟 XML “搏斗”。XML(可扩展标记语言)是当时数据交换领域的卫冕冠军。它功能强大,语法严格,而且……说实话,有点臃肿。

一个 XML 文档非常冗长。每一条数据都被包裹在开始和结束标签里。

<user>
  <id>123</id>
  <name>Alex</name>
  <isAdmin>true</isAdmin>
</user>

这还不算太糟,但就是有点笨重。更重要的是,在浏览器语言 JavaScript 中解析它简直是场噩梦。你必须在一个复杂的文档对象模型(DOM)中导航,处理节点、属性和文本内容。感觉就像杀鸡用牛刀。

这时,Douglas Crockford 出现了,他当时在一家后来成为 Yahoo! 的公司工作。他发现了一个绝妙的点子:JavaScript 本身就有一种非常好的、内置的方式来定义结构化数据。它被称为“对象字面量表示法”。

// 这就是纯粹的 JavaScript!
var user = {
  "id": 123,
  "name": "Alex",
  "isAdmin": true
};

Crockford 意识到,这个 JavaScript 语法的子集本身就是一种极佳的数据格式。它轻量、易于人类阅读,而且——这是它的杀手级特性——对于 JavaScript 来说解析起来简直不费吹灰之力。你基本上可以直接 eval() 它(尽管出于安全原因,我们现在使用像 JSON.parse() 这样更安全的方法)。

他将这种格式规范化,给它取名为 JavaScript Object Notation (JSON),并创建了一个简单的单页网站来解释它。它解决了一个问题:我们需要一种比 XML 更轻量、并且原生于 Web 环境的数据格式。JSON 如野火般蔓延开来,成为 API、配置文件和无数其他应用事实上的标准语言。它之所以能赢,是因为它简单、实用,并且源于它所要服务的那门语言。

底层工作原理

JSON 的核心就是一套将数据写成文本的规则。把它想象成数据结构的通用蓝图。它只有两种组织结构的方式和六种可以放入其中的简单数据类型。

基本构建块:数据类型

JSON 的优雅之处在于其极简的值类型集合。JSON 中的一切都是这些类型之一。

类型 示例 描述
String (字符串) "Hello, world!" 一串 Unicode 字符,用双引号包裹。
Number (数字) 42, -3.14, 2.99e8 整数或浮点数。没有 NaN 或 Infinity。
Boolean (布尔值) true, false 逻辑上的真和假,始终为小写。
Null (空值) null 表示有意设置的空值,始终为小写。
Array (数组) [1, "two", false] 一个有序的值列表,用方括号 [] 括起来。
Object (对象) {"key": "value"} 一个无序的键值对集合,用花括号 {} 括起来。

就这些。没有日期、没有函数、没有特殊类型。这种简洁性是一种特性,而不是缺陷,因为它保证了数据几乎可以被任何编程语言所理解。

结构:对象和数组

真正的魔法发生在你组合这些基本构建块的时候。

  • 对象用于当你有一组命名的东西时。其中的“键”(名称)必须是放在双引号里的字符串。“值”可以是六种数据类型中的任意一种,包括另一个对象或数组。这就是你创建层级结构的方式。

  • 数组用于当你有一个有序的东西列表时。顺序很重要,你可以通过它们的位置(索引,从零开始)来访问项目。

让我们来构建一个简单的用户个人资料。它是一个对象,因为它有像 name 和 email 这样的命名属性。其中一个属性 skills 是一个列表,所以我们使用数组。

{
  "userId": "u-9a8b7c",
  "username": "CodeWizard",
  "isActive": true,
  "lastLogin": null,
  "profile": {
    "realName": "Dana Scully",
    "location": "Washington, D.C."
  },
  "skills": [
    "Forensic Pathology",
    "Firearms",
    "Rational Skepticism"
  ]
}

看到嵌套了吗?一个对象(profile)是主对象内部的一个值。一个数组(skills)是另一个值。这种树状结构可以根据需要进行任意深度的嵌套,让你能够模拟极其复杂的数据。

在 JavaScript 中,访问这些数据非常直观: data.username 会得到 "CodeWizard"。 data.profile.realName 会得到 "Dana Scully"。 data.skills[0] 会得到 "Forensic Pathology"。

这种与原生语言结构的直接映射正是开发者喜爱它的原因。

语法规则

要成为一个有效的 JSON,你必须遵守一些严格的规则。正是这种严格性使其能够被机器可靠地解析。

  1. 只能用双引号: 所有的键和所有的字符串值都必须用双引号(")括起来。单引号(')是语法错误。
  2. 不能有尾随逗号: 逗号用于分隔数组中的元素或对象中的键值对。你不能在最后一个元素后面加逗号。
    // 错啦!'true' 后面多了个逗号
    {
      "key1": "value1",
      "key2": true, 
    }
    
  3. 对象和数组: 数据通过对象({})或数组([])来组织。一个有效的 JSON 文档可以是一个单一的值(比如字符串 "hello"),但顶层容器几乎总是一个对象或数组。
  4. 空白字符很灵活: 在字符串之外的空格、制表符和换行符都无所谓。这使得既可以有用于人类阅读的“漂亮”缩进格式,也可以有用于高效网络传输的“压缩”单行格式。

真实世界的应用案例

社交媒体信息流

前端开发者 Maya 的任务是为一个新的社交网络构建无限滚动的信息流。每当用户滚动到页面底部附近时,她的 JavaScript 代码就需要向服务器请求更多的帖子。服务器返回的不是 HTML,而是纯数据。它发送一个 JSON 数组,其中每个元素都是一个代表帖子的对象。这个对象包含帖子的文本、作者的用户名、头像链接、点赞数,甚至还有一个包含前几条评论的嵌套数组。Maya 的代码接收到这个干净的 JSON,遍历数组,然后动态创建每个帖子的 HTML,并将其附加到页面上。

经验之谈: JSON 是现代动态 Web 应用的生命线,充当了服务器大脑和浏览器表示层之间的轻量级信使。

游戏配置

独立游戏开发者 Leo 正在创作一款角色扮演游戏。他需要管理成百上千的物品:剑、药水、盔甲等等。如果将每个物品的属性(名称、伤害、重量、价格)直接硬编码到游戏的 C++ 代码中,那么在平衡和更新时将是一场噩梦。于是,他创建了一个 items.json 文件。这是一个巨大的 JSON 对象,其中每个键都是一个物品 ID(比如 "longsword"),值是另一个包含其所有属性的对象。游戏开始时,它会读取这个文件并将所有物品数据加载到内存中。为了重新平衡游戏,他只需要编辑这个文本文件,无需重新编译。

经验之谈: JSON 是配置文件的一种绝佳格式,它将应用程序的数据与其逻辑分离,并使其易于被人类编辑。

微服务交响曲

后端工程师 Fatima 在一个由几十个微服务组成的系统上工作。一个“用户服务”管理用户账户,一个“订单服务”管理购买,还有一个“通知服务”发送电子邮件。当用户下订单时,订单服务需要确认用户的收货地址。它不直接查询数据库,而是向用户服务的 API 端点发出 HTTP 请求,比如 GET /api/users/123/address。用户服务返回一个简单的 JSON 对象:{"street": "123 Main St", "city": "Anytown"}。订单服务解析这个 JSON,验证订单,然后向通知服务发送一个请求(同样带有 JSON 负载)来发送收据邮件。

经验之谈: 在一个分布式系统中,JSON 充当了一种通用的、与语言无关的契约,使得用 Go、Python 和 Node.js 编写的服务能够无缝地相互通信。

常见错误和陷阱

  • 尾随逗号: 这是最常见的验证错误。JavaScript 的数组和对象通常更宽容,但 JSON 是严格的:集合中的最后一个元素后面不能有逗号。
  • 注释: JSON 没有注释。句号。习惯了 // 或 /* */ 的开发者经常试图添加注释,但这会立即使 JSON 无效。“官方”的奇技淫巧是添加一个像 "_comment": "你的注释写在这" 这样的键,解析器会将其视为另一条数据。
  • 单引号 vs. 双引号: 所有的键和所有的字符串都必须使用双引号(")。如果你是从 Python 字典或某些 JavaScript 风格指南过来的,你可能习惯用单引号,但在 JSON 中这是禁止的。
  • undefined 这玩意儿不存在: 在 JavaScript 中,一个缺失的对象属性是 undefined。JSON 没有这个概念。要表示一个缺失或空的值,你必须明确使用 null。
  • 未转义的引号: 如果你的字符串值需要包含一个双引号,你必须用反斜杠(\)来转义它。忘记这一点({"quote": "She said "Hello""})会破坏结构。正确的方式是 {"quote": "She said \"Hello\""}。

为什么你应该关注它

在现代软件开发中,JSON 不仅仅是“值得关注”;它就是行业标准。它在如此多关键任务中都是默认格式,以至于不熟悉它就像一个不知道盐是什么的厨师。

无论何时,只要你遇到以下情况,都应该首先想到 JSON:

  • 你正在构建或使用一个 Web API。
  • 你需要一个应用程序的配置文件。
  • 你需要将结构化数据存储在一个简单的文本文件或像 MongoDB 这样的 NoSQL 数据库中。
  • 你正在从服务器端进程向客户端 JavaScript 应用程序发送数据。
  • 你需要一种简单、人类可读的格式来序列化一个对象,以便通过网络发送或保存到磁盘。

基本上,如果你需要让两个不同的程序相互交谈,或者你需要将数据与代码分离,JSON 几乎总是你的首选最佳答案。

深入了解

理论搞定,动手试试吧——100% 在你的浏览器中运行。

试用工具: JSON 查看器