基于documentation,我希望JSON_UNESCAPED_LINE_TERMINATORS
在编码JSON时保留未转义的换行符(\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"}
(Note这是一个有效的JSON;只有\
和"
* 必须 * 在字符串中转义。)
为什么这个选项不像预期的那样工作?
2条答案
按热度按时间5lhxktic1#
[编辑]我错误地阅读了JSON规范:字符串中未编码的换行符 * 不是 * 有效的JSON。从U+0000到U+001 F * 的控制字符 * 必须 * 被转义。PHP不包含未编码的换行符是正确的,尽管文档显然可以改进!
我必须去源代码才能找到答案。在这种情况下,“行终止符”仅指晦涩的Unicode代码点U+2028 LINE SEPARATOR和U+2029 PARAGRAPH SEPARATOR:
这与Unicode定义的行结束符相冲突:
Unicode标准定义了许多字符,符合标准的应用程序应将其识别为行终止符:
6g8kf2rb2#
这是一些冲突规范的结果。
然而,JSON和javascript对什么构成“行结束”有不同的定义,JSON更宽松。JSON允许U+2028和U+2029,但javascript没有。(我在这里说的是过去式,因为ES 5更新了javascript的规范,允许它们。)
与此同时,PHP会尽力保证您的安全。例如,默认情况下,它会转义
/
,即使它不需要按照规范进行转义,以防您在HTML中嵌入JSON,并可能在JSON中包含文本</script>
,这会破坏HTML。因此,默认情况下,PHP会使其成为<\/script>
。您可以使用JSON_UNESCAPED_SLASHES
关闭此功能,但实际上并不需要这样做,除非你真的想减少有效负载中的字节数。任何JSON解析器都会将/
和\/
视为相同。默认情况下,PHP也会转义所有非ASCII字符。有更多的理由关闭它,让你的JSON更容易阅读,也可以保存更多的字节,你可以用
JSON_UNESCAPED_UNICODE
来做到这一点。但是,现在,你有可能在你的数据中出现那些讨厌的行结尾,这可能会破坏一些解析器。(具体来说,他们会破坏javascripteval()
pre-ES 5,您可能不应该使用它来解析JSON,但有些人会这样做。使用与转义正斜杠相同的逻辑,尽管这在技术上是不必要的。所以这两个字符默认编码。几乎不需要关闭它 *,但是如果您确实想关闭,JSON_UNESCAPED_LINE_TERMINATORS
为您提供了选项。如果你没有使用
JSON_UNESCAPED_UNICODE
,所有非ASCII字符都会被转义,所以JSON_UNESCAPED_LINE_TERMINATORS
没有任何作用。注意:与
JSON_UNESCAPED_SLASHES
的比较不是我自己的:它是在the Github discussion proposing this change in PHP中提出的。