技术 · 入门

Node.js 与 JSON:为什么它成了标准

一项技术能统一,往往是因为它让得够多
JSON 赢下所有语言,不是因为它能表示得多,是因为它砍到只剩六种值。同一套语法,Python 读得懂、Go 读得懂、浏览器和 Node 都读得懂,因为在它出现之前,没有一种格式是所有语言都肯认的。这一篇先讲 Node 是什么,再讲那六种值为什么能当最大公约数。
一 · Node 不是一门新语言
先把最容易误会的一点说清:Node.js 不是 JavaScript 的方言,也不是新语言。它就是 JavaScript,只是换了个地方跑。原本 JS 只能在浏览器里跑,因为浏览器提供了它运行所需的环境;Node 把这个环境重做了一份,搬到操作系统上。
语法一行没变。变的只是它能碰到的世界:浏览器里的 JS 能操作页面,但碰不到你的硬盘;Node 里的 JS 碰不到页面,但能读写文件、开网络端口、启动子进程。你在浏览器里做不到的那些事,才是 Node 存在的理由。
它用的引擎是 V8,也就是 Chrome 里那个。这一点解释了为什么同一个函数在两边行为一致:底层是同一份代码在跑。
二 · 一个最小的 Node 程序
1
建一个 .js 文件 —— 里面写的是普通 JavaScript。没有专属语法,没有类库要求,一行 console.log 就能跑。
2
在终端敲 node 文件名 —— 和 python 文件名是同一个意思:把这个文件交给运行时执行。
3
要用系统能力就引入内置模块 —— 读写文件、起服务、拿路径,这些都是内置的,不需要装任何东西。
4
它是单线程的 —— 这一条决定了写法:等文件、等网络时不要停在那里,而是把后续动作交给回调或 Promise。
最后一条最容易被跳过,但它解释了 Node 为什么适合做接口服务:大部分时间不是算,是在等。等磁盘、等数据库、等另一个服务返回。单线程加上异步,正好把等待的时间让给别人。
三 · JSON 为什么能统一
JSON 的全名是 JavaScript Object Notation,但它现在的地位跟 JavaScript 没什么关系了。它的语法是从 JS 的对象字面量里借来的,只借了一部分:函数、注释、undefined、单引号这些统统没有。
砍完剩下的只有六种值:对象、数组、字符串、数字、布尔、null。而这六种,每一种主流语言都有对应的东西。这就是它能统一的原因——不是因为它能表示得多,是因为它要求得少。
它砍掉了什么,为什么砍
函数
1. 函数是「行为」,不是「数据」。写进数据文件里,读的一方没法执行它。
2. 想要表达「要执行什么」,正确做法是写一个字符串,比如操作名。
3. 少了它,格式就从「程序」退回到「数据」—— 这一步退让换来了所有语言都能读。
注释
1. 注释是给人看的,机器不需要。放进传输格式里,会多出一堆要解析又不能丢的东西。
2. 代价是很具体的:配置文件里没法写说明,只能靠旁边的文档或者专门的字段。
3. 这是一个明确的取舍,不是遗漏。
日期类型
1. 时间在 JSON 里只能是字符串,格式靠约定(通常是 ISO 8601)。
2. 于是「这是本地时间还是 UTC」变成两边必须事先说好的事。
3. 跨时区出问题,多半就出在这一步。
整数精度
1. 数字只有一种类型,按浮点数处理。
2. 超过一定位数的整数会失真,比如订单号、用户 ID 长得像数字的那些。
3. 稳的做法是把这类值当字符串传,代价是读的一方要多转一次。
把它和 XML 放在一起看更清楚:XML 什么都能表示,所以什么都要约定(命名空间、schema、编码)。能表示的越多,两边要谈的条款就越多。JSON 只规定「怎么写」,一个字都不规定「是什么意思」—— 意思留给用的人。
四 · 接口为什么都返回 JSON
因为 HTTP 传的是文本。不管服务端手里的数据是什么结构,最终发出去的都是一串字符;客户端收到的也是一串字符。中间必然有两次转换:发之前把对象变成字符串,收之后把字符串变回对象。
1
服务端序列化 —— 把内存里的对象写成一串文本。在 Node 里就是 JSON.stringify。
2
走网络 —— 这一层完全不知道里面是什么,它只负责把字节送到。
3
客户端反序列化 —— 把文本变回对象。在 Node 和浏览器里都是 JSON.parse。
这两个函数在几乎所有语言里都是标准库自带的,不用装包。所以「接口为什么用 JSON」这个问题,答案不是「它好看」,而是两端都自带这两个函数,多一层依赖都不用加。
还有一个容易忽略的细节:JSON 的键必须用双引号包起来。不是因为格式挑剔,是因为在 JSON 里键就是一个字符串,而字符串必然带引号——这一点和 JS 对象字面量不一样,那边不写引号也行。
五 · 什么时候别用 JSON
它适合传结构化的小数据,不适合两种情况:一是体积大的二进制(图片、音视频),base64 编码进去会变大三分之一;二是需要保留类型的信息,比如日期、超大整数、精确小数。
还有一种是「人和机器都要读」的配置。JSON 不能写注释,所以配置一复杂,很多人会换 YAML——这不是 JSON 不够好,是它当初就没打算服务这个场景。
验证只看三问:① 能不能说清 Node 和浏览器里的 JS 差在哪?② 能不能说出 JSON 砍掉的那几样里,哪一样是你真的会想念的?③ 拿到一个接口返回,能不能指出哪个字段本该是字符串却给了数字?第一问答不出「能碰到什么」⇒ 还停在「Node 是后端语言」这个模糊说法上;第二问答「注释」⇒ 说明你在用它写配置,那就该换格式了。
[B级]JSON 语法定义见 RFC 8259;Node.js 官方文档说明其基于 V8 引擎[C级]取舍判断与踩坑清单为经验整理,非规范原文