JSON 与 JavaScript 文字

JSON 代表 JavaScript Object Notation,但它不是 JavaScript。可以把它看成只是一个数据序列化格式,恰好是可直接用作一个 JavaScript 字面。但是,不建议直接运行(即通过 eval())从外部源获取的 JSON。从功能上讲,JSON 与 XML 或 YAML 没有什么不同 - 如果将 JSON 想象成一种看起来非常像 JavaScript 的序列化格式,则可以避免一些混淆。

即使名称仅仅意味着对象,即使通过某种 API 的大多数用例总是碰巧是对象和数组,JSON 也不仅仅是对象或数组。支持以下基元类型:

  • 字符串(例如 Hello World!
  • 数字(例如 42
  • 布尔值(例如 true
  • 价值 null

在序列化时将从 JSON 中省略未定义属性的意义上不支持 undefined。因此,无法反序列化 JSON 并最终获得值为 undefined 的属性。

字符串 42 是有效的 JSON。JSON 并不总是必须有 {...}[...] 的外部信封。

虽然 nome JSON 也是有效的 JavaScript,而一些 JavaScript 也是有效的 JSON,但两种语言之间存在一些细微差别,而且两种语言都不是另一种语言的子集。

以下面的 JSON 字符串为例:

{"color": "blue"}

这可以直接插入 JavaScript。它在语法上是有效的,并将产生正确的值:

const skin = {"color": "blue"};

但是,我们知道 color 是有效的标识符名称,并且可以省略属性名称周围的引号:

const skin = {color: "blue"};

我们也知道我们可以使用单引号而不是双引号:

const skin = {'color': 'blue'};

但是,如果我们要同时使用这两个文字并将它们视为 JSON,那么它们在语法上都不是有效的 JSON:

{color: "blue"}
{'color': 'blue'}

JSON 严格要求所有属性名称都是双引号,并且字符串值也要双引号。

JSON 新手尝试使用 JavaScript 文字的代码摘录作为 JSON 是常见的,并且对他们从 JSON 解析器获得的语法错误感到不满。

当在代码或对话中应用不正确的术语时,会出现更多混淆。

常见的反模式是将包含非 JSON 值的变量命名为 json

fetch(url).then(function (response) {
  const json = JSON.parse(response.data); // Confusion ensues!

  // We're done with the notion of "JSON" at this point,
  // but the concept stuck with the variable name.
});

在上面的示例中,response.data 是一些 API 返回的 JSON 字符串。JSON 在 HTTP 响应域停止。带有 jsonmisnomer 的变量只包含一个 JavaScript 值(可能是一个对象,一个数组,甚至是一个简单的数字!)

写上述内容的一种不那么令人困惑的方式是:

fetch(url).then(function (response) {
  const value = JSON.parse(response.data);

  // We're done with the notion of "JSON" at this point.
  // You don't talk about JSON after parsing JSON.
});

开发人员也倾向于抛出“JSON 对象”这个短语。这也会导致混淆。因为如上所述,JSON 字符串不必将对象保存为值。 “JSON 字符串”是一个更好的术语。就像 XML stringYAML string 一样。你得到一个字符串,你解析它,你最终得到一个值。