首页/文章/javascript

JSON 的键为什么必须有引号?

2024-10-08
21838 分钟
...

00. 写作背景

如题,为什么 JSON 的键被设计为必须有引号

但是,问题无厘头,不代表无意义。Vite 源码的 pnpm 配置使用了一种 YAML 格式的配置文件,很多工具和语言也支持 YAML。

举个栗子,这是格式化工具 Prettier 官网的示例:

粉丝请注意,YAML 和 JSON 一龙一猪,键名真的可以没引号!那么,强制要求键名加引号、而且必须是双引号的 JSON 到底在搞什么飞机?

有时候,乍一看是几何题,其实是函数题。我发现只要使用第一性原理深度思考,就能求解女粉的知识盲区。

事实上,为什么 JSON 的键会被引号裹挟,其实更准确的等价问法是:

  • 为什么不能没有引号,比如 JSON?
  • 为什么必须是双引号,比如 "JSON"?
  • 为什么不能是单引号,比如 'JSON'?
  • 为什么不能是反引号,比如 JSON?

01. 为什么不能没有引号?

一句话解释,无引号的 JSON 发明失败了,就像本人的初恋一样悲剧......

根据 JSON 官网,JSON 是一种轻量级数据交换格式。既然是数据交换格式,JSON 的首秀自然是用于数据通信。

“JSON 之父”在地球上测试的第一条 JSON 消息类似如下:

可以看到,这是一段测试 JSON 数据通信的普通脚本。粉丝请注意,这里 JSON 的键并没有引号,和 JS 对象字面量一模一样。

根据 JSON 官网,JSON 是一个基于 ES3 的子集,所以这种雷同 JS 对象字面量的格式完全合法。不幸的是,就跟其他许多“第一次”一样,JSON 的首秀萎了。那么,上述代码到底有何 bug 呢?

bug 在于,ES3 的保留字策略十分猪头。上述代码中,do 属性是 ES3 的同名保留字之一,而 ES3 规定,禁止保留字作为标识符。换而言之,do 保留字无法作为合法的 JSON 键名,否则运行时就会报错。

于是乎,“JSON 之父”掏出来的解决方案就是给键名加上引号,这样 do 保留字就变成了 "do" 字符串。举一反一,所有和保留字同名的特殊文本也可以作为 JSON 的合法键名。比较专业的措辞是,通过添加引号来让 JSON 文本化。

02. 为什么必须是双引号?

地球人都知道,发射双引号需要同时按下 shit + 引号键,而发射单引号只需要按下引号键就欧了,显然单引号更符合人体工程学,开发体验就跟点赞一样人性化。

比较意外的是,如今的 JSON 却反而采用了双引号......这不科学!

你知道的,JS 和 Java 一龙一猪。在 Java 等编程语言中,双引号表示的是字符串,单引号表示的却是字符。

举个栗子,这是从菜鸟教程拷贝过来的一个 Java 示例(免责声明,因为我只会 JS):

可以看到,JS 可以不关心 字符 vs 字符串 的区别,而 Java 则会通过不同引号明确区分。

因此,作为全栈通吃的数据交互格式,JSON 的设计必须共情或 PUA 其他编程语言,格式必须尽量符合各种语言的编程直觉。这种设计就是基于 用户思维 —— 双引号可以尽量兼容各种语言的习惯,它大概率是“字符串”。

03. 为什么不能是单引号?

俗话说得好,两手都要抓,两手都要硬。JSON 采用双引号是基于用户思维,但为什么不能像 JS 一样,顺便兼容单引号呢?

举个栗子:

这是因为,“最小化原则”让“JSON 之父”必须在单/双引号中“零和博弈”,两权相重取其轻。“JS 之父”曾经直言,“JSON 之父”是一位“极简主义者”。显然,JSON 的减法设计既符合“JSON 之父”的品味,也符合“JS 子集”的人设。

但这不仅仅是设计者的个人偏好,你知道的,JSON 是与编程语言无关的数据交换格式。这意味着,JSON 最好能够跨语言,只支持一种引号的解析器更容易被不同语言实现,JSON 爱好者的学习曲线也更加平滑。

总之,只支持单引号更有利于推广 JSON。事实上,JSON 确实找到了“流量密码”,成为地球上人气爆棚的数据交换格式之一。

04. 为什么不能是反引号?

这可能是像我一样的 JS 爱好者才会深度思考(纠结)的问题,前文提及的用户思维和极简主义其实已经暴露了部分原因。

此外,根据 JSON 官网,JSON 一直都是基于 ES3 的子集。这意味着,JSON 一定是合法的 JS 对象字面量;反之,JS 对象字面量未必是合法的 JSON。

反引号其实是后 ES6 时代的 JS 爱好者才会接触的语法,ES6 为了区分模板字符串专门加入了反引号。在 JS 中,反引号并不像单双引号那么通用。

可以看到,反引号既不是 JS 字符串的主流风格,也无法用来定义 JS 对象字面量的属性。

因此,作为 ES3 的子集,JSON 当时根本不会考虑反引号,以后也不会考虑。

05. 高潮总结

“JSON 之父”说过,我并没有 发明 JSON,我只是在 JS 的语法中 发现 了 JSON。

后来,我终于学会了如何去解读其中的含义。哪怕只是一种轻量的数据交换格式,JSON 键的设计也细节满满:

  • 为什么不能没有引号?历史包袱。
  • 为什么必须是双引号?用户思维。
  • 为什么不能是单引号?极简主义。
  • 为什么不能是反引号?历史虚无。

参考文献

  1. JSONwww.json.org/json-en.htm…
  2. GitHubgithub.com/tc39/propos…
  3. Prettierprettier.io/docs/en/con…

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
javascript2025-09-18
JavaScript 的多线程能力:Worker
如果你写过一些计算量稍大的 JavaScript 代码,比如图像处理、大量数据排序或者复杂的算法,你几乎肯定遇到过浏览器“卡死”的现象。点击页面没反应,动画也停了,就像整个世界都静止了。 这就是主线程被阻塞的典型后果。因为主线程既要负责执行 JavaScript,又要负责渲染页面、响应用户操作,一旦它被繁重的计算任务占满,就无暇顾及其他,用户体验便直线下降。 这个问题的根源,正是“主线程是单线程的”。那么,如何解决呢? 答案很简单:把这...
学习面试
javascript2025-09-10
手把手教你实现一个EventEmitter
你是不是也遇到过这种情况:代码里各种事件监听和触发,回调函数套了一层又一层,最后自己都理不清哪个事件先触发、哪个后触发了? 别担心,今天我就带你从零开始实现一个自己的事件触发器(EventEmitter),让你彻底掌握事件驱动的精髓,代码清晰度直接提升200%! 为什么要懂EventEmitter? 先说说为什么我们要关心这个。Node.js的核心就是事件驱动,比如文件读写、网络请求,都是通过事件来处理的。不会EventEmitter,...
学习面试
javascript2025-08-09
Web Worker 多线程魔法
你是否曾遇到过网页因为复杂计算而卡顿的情况?今天,让我们一起探索Web Worker的神奇世界,看看如何用多线程技术解决性能瓶颈,并实现流畅的图片压缩功能! 为什么需要Web Worker? 想象一下,你在一个繁忙的餐厅里,只有一位服务员(主线程)负责点餐、上菜、结账所有工作。当客人突然暴增时,这位服务员就会手忙脚乱,其他客人只能干等着… 这就是JavaScript的现状—— 单线程 !所有任务都在一个线程中排队执行,一旦遇到复杂计算(...
学习面试
javascript2025-08-07
🌐AST抽象语法树
AST 是前端开发中一个非常重要的概念,它就像是代码的“编译器”,能够帮助我们理解和操作代码。本文将深入探讨 AST 的原理和应用,带你从零开始了解 AST。 一、什么是 AST? AST(抽象语法树)是一种树形结构,用于表示程序代码的语法结构。它将代码分解为一系列的节点,每个节点代表代码中的一个元素,如变量、函数、表达式等。AST 是编译器和解释器的基础,也是代码分析和转换的关键工具。 1\. AST 的结构 AST 的结构通常包括以...
学习面试
javascript2025-08-05
打字机效果是如何实现的
分析效果 使用 AI 对话的时候,文字是一个字一个字蹦出来的?它不是等所有内容生成完毕后一次性展示,而是以一种流畅、实时的“打字机”效果呈现,这种体验的背后,隐藏着一种高效的Web技术。它就是 服务器推送事件(Server Sent Events,简称 SSE) 什么是 SSE 从根本上说,SSE 是一种允许服务器 单向 、 持续 地向客户端(浏览器)推送数据的Web技术。 可以把它想象成一个 电台广播 : 服务器 是广播电台,持续不断...
学习面试
javascript2025-08-04
Promise 从原理到实现
前言 是 异步编程的核心概念之一,它为我们提供了一种更优雅的方式来处理异步操作。 本文将全面剖析 的工作原理,并逐步实现一个符合 规范的 。 正文 一、Promise 基础概念 代表一个异步操作的最终完成(或失败)及其结果值。它有 种状态: 1. pending : ,既不是成功,也不是失败状态 2. fulfilled :意味着操作 完成 3. rejected :意味着操作 状态一旦改变就不能再变,只能从 变为 ,或从 变为 。 二...
学习面试

评论

请登录后发表评论

去登录
加载评论中...

目录