For AI agents: the complete documentation index is available at /tc39-atlas/llms.txt, the full documentation bundle is available at /tc39-atlas/llms-full.txt, and this page is available as Markdown at /tc39-atlas/proposals/year/2019/proposal-well-formed-stringify.md.
  • 简体中文
  • Well-formed JSON.stringify S4

    提案概览
    提案速览

    该提案解决了 JSON.stringify 可能返回包含未配对代理码点的格式不正确的 Unicode 字符串的问题,这些字符串不是有效的 UTF-8 或 UTF-16。它提议用 JSON 转义序列(例如 \udf06)来表示此类未配对的代理,同时保留有效代理对的序列化。

    Note

    以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。

    Well-formed JSON.stringify

    一个防止 JSON.stringify 返回格式不正确的 Unicode 字符串的提案。

    状态

    该提案处于 TC39 流程 的第 4 阶段。

    champions

    • Mathias Bynens

    动机

    RFC 8259 第 8.1 节 要求,在封闭生态系统范围之外交换的 JSON 文本必须使用 UTF-8 编码,但 JSON.stringify 可能返回包含在 UTF-8 中无法表示的码点的字符串(具体来说,即 U+D800 到 U+DFFF 范围的代理码点)。 而且,与 JSON.stringify 的描述 相反,此类字符串并非“在 UTF-16 中”,因为根据 Unicode 标准,版本 10.0.0,第 3.4 节 定义 D91,“D800₁₆..DFFF₁₆ 范围内的孤立 UTF-16 代码单元是格式不正确的”,并根据定义 D89 被排除在“在 UTF-16 中”之外。

    然而,返回此类无效的 Unicode 字符串是不必要的,因为 JSON 字符串可以包含 Unicode 转义序列。

    提议的解决方案

    与其将未配对的代理码点返回为单个 UTF-16 代码单元,不如用 JSON 转义序列来表示它们。

    示例

    // 非 BMP 字符仍序列化为代理对。
    JSON.stringify('𝌆')
    // → '"𝌆"'
    JSON.stringify('\uD834\uDF06')
    // → '"𝌆"'
    
    // 未配对的代理代码单元将序列化为转义序列。
    JSON.stringify('\uDF06\uD834')
    // → '"\\udf06\\ud834"'
    JSON.stringify('\uDEAD')
    // → '"\\udead"'

    讨论

    向后兼容性

    在消费者符合 JSON 规范的假设下,此变更向后兼容。 对用户可见的影响将仅限于将 JSON.stringify 输出中的一些罕见的单个 UTF-16 代码单元替换为等效的六字符转义序列,这些序列可以在 UTF-16 和 UTF-8 中表示。 作者认为,任何接受当前格式不正确输出的消费者都不会受到此变更的影响(尤其是 ECMAScript 的 JSON.parse 也是如此)。 任何拒绝当前格式不正确输出的消费者将有机会接受其格式正确的表示,尽管此类消费者可能仍然拒绝指定包含非标量值的 Unicode 码点的字符串输入(例如,因为他们只接受 I-JSON 输入),但那些接受它的消费者必须有处理未配对代理的机制(如 JSON 规范中所述)。

    有效性

    Unicode 转义序列是有效的 JSON,并且完全由 ASCII 组成,因此它们是 UTF-16 和 UTF-8 中的格式正确的表示。

    规范

    规范可在 ecmarkup渲染的 HTML 中获得。

    实现