首页 > 解决方案 > 为什么 JSON_UNESCAPED_LINE_TERMINATORS 没有取消我的换行符?

问题描述

根据文档,我希望在编码 JSON 时JSON_UNESCAPED_LINE_TERMINATORS保留未\n转义的换行符(),因此作为实际的换行符:

JSON_UNESCAPED_LINE_TERMINATORS(整数)
行终止符在JSON_UNESCAPED_UNICODE提供时保持未转义。它使用与没有此常量的 PHP 7.1 之前相同的行为。自 PHP 7.1.0 起可用。

最小的例子:

$ php -r 'echo json_encode(["foo" => "bar\nbaz"], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS) . "\n";'
{"foo":"bar\nbaz"}

我期望:

{"foo":"bar
baz"}

(请注意,这是有效的 JSON;仅\" 必须在字符串中转义。)

为什么此选项不能按预期工作?

标签: phpjson

解决方案


[编辑] 我错误地阅读了 JSON 规范:字符串中未编码的换行符不是有效的 JSON。从 U+0000 到 U+001F 的控制字符必须进行转义。PHP 不包括未编码的它们是正确的,尽管文档可以明显改进!

我不得不去源头找到这个。此上下文中的“行终止符”仅指晦涩的 Unicode 代码点 U+2028 LINE SEPARATOR 和 U+2029 PARAGRAPH SEPARATOR:

                /* Escape U+2028/U+2029 line terminators, UNLESS both
                   JSON_UNESCAPED_UNICODE and
                   JSON_UNESCAPED_LINE_TERMINATORS were provided */
                } else if ((options & PHP_JSON_UNESCAPED_UNICODE)
                    && ((options & PHP_JSON_UNESCAPED_LINE_TERMINATORS)
                        || us < 0x2028 || us > 0x2029)) {

这与 Unicode定义为行终止符的内容相冲突:

Unicode 标准定义了许多符合标准的应用程序应识别为行终止符的字符:

LF:    Line Feed, U+000A
VT:    Vertical Tab, U+000B
FF:    Form Feed, U+000C
CR:    Carriage Return, U+000D
CR+LF: CR (U+000D) followed by LF (U+000A)
NEL:   Next Line, U+0085
LS:    Line Separator, U+2028
PS:    Paragraph Separator, U+2029

推荐阅读