简体中文

开发者工具 · JSON 格式化程序和验证程序

JavaScript 对象文字与 JSON:为什么单引号验证失败

· 工作原理

json 开发人员工作流程 验证

JavaScript 对象文字与 JSON:为什么单引号无法通过 JSON 标记和精确验证边界进行验证
原始 ToolAcre 矢量图

JavaScript 控制台打印的对象看起来像 JSON 但通常不是。这篇文章列出了确切的差异(引号、未加引号的键、未定义、函数),并显示了每个差异触发验证器的位置。

从控制台出来了,为什么无效呢?

从控制台出来了,为什么无效呢? — 开发者控制台将 JavaScript 值显示为 JavaScript 源代码文本,而不是有保证的 JSON 序列化。复制的对象可能包含裸属性名称、单引号字符串、`undefined` 或特定于浏览器的注释。所有这些对于 JavaScript 引擎或人类读者来说都是可以理解的,但在 `.json` 文件中立即失败,该文件的语法故意更小并且独立于可执行代码。

考虑 `{name: "Ada", active: true, missing: undefined}`。大括号、冒号和布尔值类似于 JSON,但第一个裸键已经违反了对象成员规则,并且 `undefined` 稍后会失败。 ToolAcre 使用行和列报告第一个不受支持的字符或值,因此最好按顺序进行转换。

字符串必须使用双引号

字符串必须使用双引号 — JSON 将字符串定义为 `"` 括起来的字符,并在需要时使用反斜杠转义。单引号没有字符串分隔符的作用。当验证器满足 `'Ada'` 时,它不会以字符串开头然后反对其内容;它拒绝开头的撇号本身。这同样适用于属性名称和字符串值,即使 JavaScript 允许其自己的文字使用任一引号样式。

转换引号比全局替换每个撇号更需要小心。一旦值被双引号括起来,文本中的撇号(例如 `Ada's profile`)就是普通内容,而该内容中现有的双引号必须被转义。有效的 JSON 形式是 `"Ada's "profile""`。

键必须是带引号的字符串

键必须是带引号的字符串 - JavaScript 对象文字允许标识符样式名称(例如 `{name: 1}`)和计算名称(例如 `{[expression]: 1}`)。 JSON 不允许这两种简写形式。在左大括号或逗号之后,下一个成员必须以双引号字符串开头,后跟冒号。有效的表示是 `{"name": 1}`。指向 `n` 的验证器正在识别需要报价的确切位置。

引用每个键还可以消除空格、连字符和保留字的歧义。对于这些情况,JavaScript 可能需要不同的源语法,但 JSON 使用一个一致的规则:`"display-name"`、`"first name"` 和 `"default"` 都是普通成员名称。看起来数字的键也是字符串。

值 JSON 根本没有

值 JSON 根本不存在 — 其值词汇是对象、数组、字符串、数字、`true`、`false` 和 `null`。没有 `undefined`、`NaN`、`Infinity`、函数、正则表达式、BigInt 或 Date 文字。语法中没有注释,数字不能使用十六进制、二进制、前导加号或 JavaScript 数字分隔符。每个借用的构造最终都会到达一个无法开始或继续有效 JSON 值的字符。

转换需要数据决策而不是拼写技巧。仅当显式空值与应用程序约定匹配时,才将 `undefined` 替换为 `null` ;否则删除成员或提供实际值。将日期编码为商定的字符串,通常为 ISO 8601。根据接收 API 表示非有限数字,而不是发明 JSON 令牌。

工作示例:将控制台转储转换为有效的 JSON

工作示例:将控制台转储转换为有效的 JSON — 以 `{name: 'Ada', active: true, score: NaN, updated: new Date()}` 开头。用双引号引用 `name`、`active`、`score` 和 `updated`。将名称值更改为双引号字符串。确定不可用分数应为 `null`,并将构造函数表达式替换为它要生成的实际时间戳字符串。该文档现在仅包含 JSON 成员和值。

最终形状可能是 `{"name":"Ada","active":true,"score":null,"updated":"2026-03-21T10:00:00Z"}`。在每个修复类别之后进行验证,因为第一个错误可能会隐藏后面的纯 JavaScript 语法。格式化接受的结果然后公开其结构,而不执行任何进一步的转换。

反向陷阱 — 有效的 JSON JavaScript 会以不同的方式读取,例如非常大的整数和 __proto__ 键

反向陷阱 — 有效的 JSON 在解析后仍然可以获得 JavaScript 特定的行为或限制。 JSON 数字在语法中没有内置精度限制,但 JSON.parse 会生成 JavaScript 数字值。因此,超出安全范围的整数可以静默舍入。如果每个数字都很重要,请将标识符编码为字符串,或使用旨在保留任意精度数字的解析器和数据类型,而不是信任成功的语法检查。

成员名称 `"__proto__"` 也是有效的 JSON 并且 JSON.parse 将其创建为自己的数据属性。如果应用程序代码将已解析的属性复制到具有不安全分配或合并行为的另一个对象中,则稍后可能会出现问题。验证证明文本遵循 JSON 语法;它并不能证明每把钥匙对每个消费者来说都是安全的。

这不包括什么

这不包括 - JSON5、JSONC 和故意接受注释、尾随逗号、不带引号的名称或单引号字符串的配置语言。这些格式解决了不同的创作问题,并且需要实现自己的语法的解析器。严格的 JSON 验证器不应默默地重新解释它们,因为接受额外的语法会使其结果误导真正需要标准 JSON 的 API、包元数据和其他目标。

这种区别还排除任意 JavaScript 评估。通过 `eval` 或 Function 构造函数运行粘贴的文本仅仅是为了将对象文字转换为数据,可以执行 getter、调用或其他恶意表达式。如果源是您控制下的受信任 JavaScript,请使用 JSON.stringify 序列化实际值。如果源是不受信任的文本,则不要执行它。

要点:文字是代码,JSON 是数据

要点:文字是代码,JSON 是数据——视觉相似性并不意味着它们的语法可以互换。 JSON 需要双引号字符串和成员名称,仅允许一小部分固定值类型,并且不包含注释或可执行表达式。行列诊断标记复制源离开该语法的第一个位置。修复该点并再次验证比对控制台转储应用广泛的搜索和替换更可靠。

当您控制 JavaScript 值时,使用 JSON.stringify 生成 JSON,而不是复制其控制台表示形式。当您收到文本时,仅使用解析器解析其声明的格式,而不要将其作为快捷方式执行。成功的 JSON 验证建立的是语法,而不是数字精度、模式一致性或安全的下游属性处理。