'\u2028' Unicode 字符上的 Javascript 解析错误

IT技术 javascript unicode
2021-02-20 14:27:43

每当我在我的 javascript 源代码中使用 \u2028 字符文字并将内容类型设置为“text/html; charset=utf-8”时,我都会收到一个 javascript 解析错误。

例子:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>json</title>

    <script type="text/javascript" charset="utf-8">
    var string = '
    ';
    </script>
</head>
<body>

</body>
</html>

如果<meta http-equiv>遗漏了一切,一切都会按预期进行。我已经在 Safari 和 Firefox 上对此进行了测试,两者都表现出相同的问题。

关于为什么会发生这种情况以及如何正确解决此问题(不删除编码)的任何想法?

编辑:经过更多研究,具体问题是问题字符是使用 JSONP 返回的。然后浏览器将其解释为 u2028 作为换行符,并抛出有关字符串中无效换行符的错误。

4个回答

是的,这是 JavaScript 语言的一个特性,记录在 ECMAScript 标准(第 3 版第 7.3 节)中,U+2028 和 U+2029 字符算作行尾。因此,JavaScript 解析器将以与换行相同的方式处理任何未编码的 U+2028/9 字符。由于不能在字符串文字中放置换行符,因此会出现语法错误。

这是 JSON 设计中的一个不幸疏忽:它实际上不是 JavaScript 的一个适当子集。原始 U+2028/9 字符在 JSON 中的字符串文字中有效,并且会被 接受JSON.parse,但在 JavaScript 本身中则不然。

因此,如果您确定它明确地\u转义了这些字符,那么使用 JSON 解析器生成 JavaScript 代码才是安全的有些会,有些不会;many \u-escape 所有非 ASCII 字符,从而避免了该问题。

在第 10 版(非常新)中:“更新的语法包括......允许字符串文字中的 U+2028(LINE SEPARATOR)和 U+2029(PARAGRAPH SEPARATOR)与 JSON 对齐。” 来自ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf
2021-04-24 14:27:43
这非常有帮助。解决方法是转义 JSON,然后解析客户端。例如,stackoverflow.com /questions/9691611/... for Ruby/Rails 告诉您$.parseJSON("#{j xyz.to_json}")在服务器端模板中执行。
2021-04-26 14:27:43
不确定我是否会将其称为 JSON 中的疏忽和 Javascript 中的设计缺陷一样;将这些字符包含为换行符既奇怪又出乎意料,其他文本数据格式没有这样做。但至于 JSON,虽然它起源于 Javascript 子集,但多年来它并没有与 Javascript 绑定,并且规范没有声称它是一个子集,或者这将是一个目标。建议不要评估它,而是正确解析它。因此,除了 JSONP 用法之外,引用写作是必要的还是一件好事并不完全清楚。
2021-05-10 14:27:43
更好的是:JSON.parse(#{j.to_json.inspect})将其呈现为带有\uXXXX任何不规则字符的字符串
2021-05-16 14:27:43
您可以将 JSON 插入到类型设置为“application/json”的脚本标签中。这应该避免将 UTF-8 文本解析为 JavaScript。页面加载完成后,可以JSON.parse()通过将innerHTML脚本标签的 的作为参数来解析 JSON
2021-05-21 14:27:43

好吧,回答我自己的问题。

通常 JSON 解析器会删除这些有问题的字符,因为我正在检索 JSONP 我没有使用 JSON 解析器,相反,一旦调用回调,浏览器就会尝试解析 JSON 本身。

修复它的唯一方法是确保服务器在请求 JSONP 资源时永远不会返回这些字符。

ps 我的问题是关于 u2028,根据Douglas Crockford 的 json2 库,以下所有字符都可能导致这些问题:

'\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff'

你有那个清单的来源吗?(道格拉斯·克罗克福德(douglas Crockford)下的链接没有任何有用的地方)
2021-04-24 14:27:43
链接到 JSON-js,当 repo/文件更新时不会中断:github.com/douglascrockford/JSON-js/blob/...
2021-05-16 14:27:43

你能用\u2028, 而不是真正的字符吗?,因为 U+2028 是unicode 行分隔符,浏览器会认为它是真正的换行符,如\n.

我们不能像

x = "

"

对?但我们这样做x = "\n",所以可能是相同的概念。

是啊@klaaspieter,可能在服务器端,而如果你有这样做,也难逃\u2029
2021-04-29 14:27:43
顺便说一句,我已经对其进行了更多测试,Douglas Crockford 的实现没有抛出解析错误。
2021-05-03 14:27:43
Douglas Crockford 的 JSON 实现确实对字符串进行了转义,但仍会引发解析错误。在 Safari 中使用原生 JSON 实现,这也会引发解析错误。我们正在加载 jsonp,因此浏览器将尝试在任何其他 javascript 有机会去除任何无效字符之前解析它。我可能不得不解决这个服务器端。
2021-05-04 14:27:43

嗯,这是有道理的,因为您告诉浏览器 HTML 和脚本都使用 UTF-8,但随后您指定了一个不是 UTF-8 编码的字符。当您指定“charset=UTF-8”时,您有责任确保传输到浏览器的字节实际上是 UTF-8。在这种情况下,Web 服务器和浏览器不会为您执行此操作。

根据答案的评论,这是一个有效的 UTF-8 字符,应该正确解析。
2021-05-05 14:27:43
那么,如何解决呢?该字符是由网站用户输入的。他的数据存储在 JSON 中。每次我请求 JSON 时,我都会收到一个解析错误,因为字符在那里。我不能只是删除该字符,因为客户端很可能会再次输入它。
2021-05-20 14:27:43