【问题标题】:Why does ruby's to_json break embedded javascript?为什么 ruby​​ 的 to_json 会破坏嵌入式 javascript?
【发布时间】:2012-02-27 03:50:48
【问题描述】:

问题

在 PHP 中我会这样做

<html>
<body>
    <script>
        <?php
        $templates = array(
          'result' => file_get_contents('template.html')
          );
          echo '__templates = ' . json_encode($templates) . ';';
          ?>
    </script>
</body>
</html>

所以我在 Sinatra 中做了这个

<!DOCTYPE html>
<html>
<body>
    <script type="text/javascript">
        __templates = <%= get_templates  %>;
    </script>
</body>
</html>

我的 Sinatra 路由文件如下所示:

require 'sinatra'
require 'json'
require 'erb'

helpers do
    def get_templates
        {'result' => (erb :template2)}.to_json
    end
end

get '/' do
    erb :index
end

但是当我使用来自 jquery 的 __templates 对象时,我的 javascript 对象最终被破坏了。

ruby 的 to_json 做了哪些 PHP 不做的事情?

php结果

{"result":"<!doctype html>\n<html>\n\n<head>\n\t<meta charset=\"UTF-8\">\n\t<title>{{ TITLE }}<\/title>\n\n\t<style type=\"text\/css\">\n\t{{ CSS }}\n\t<\/style>\n<\/head>\n\n<body>\n\n\t{{{ HTML }}}\n\n\t<script src=\"{{{ JSLIB }}}\"><\/script>\n\t<script src=\"{{{ PREFIX }}}\"><\/script>\n\t<script>\n\t\tfunction __run() {\n\t\t\t{{{ JS }}}\n\t\t}\n\t<\/script>\n\n<\/body>\n\n<\/html>"}

红宝石结果

{"result":"<!doctype html>\n<html>\n\n<head>\n    <meta charset=\"UTF-8\">\n    <title>{{ TITLE }}</title>\n\n    <style type=\"text/css\">\n        {{ CSS}}\n    </style>\n</head>\n\n<body>\n\n    {{{ HTML }}}\n\n    <script src=\"{{{ JSLIB }}}\"></script>\n    <script src=\"{{{ PREFIX }}}\"></script>\n    <script>\n        function __run() {\n            {{{ JS }}}\n        }\n    </script>\n\n</body>\n\n</html>\n"};

注意 php 版本上的&lt;\/body&gt;

解决方案(暂时)

我找到了一个基于下面发布的 cmets 的解决方案。但是,我不确定这是否是“一种真正的方式”,如果存在的话。 注意:我想知道这个实现是否会在未来打破其他东西。我将在整个应用程序中依赖此函数。

我最终只是使用gsub 来解决我的问题。我将它包裹在这样的助手中

helpers do
    def close embedded_json
        embedded_json.gsub('</', '<\/')
    end
    ...
end

这样称呼它

__templates = <%= close get_templates  %>;

看起来很笨拙,但在幕后,也许在 rails 中提到的助手做同样的事情?我现在要继续前进,但我仍然想知道以后我是否会因此而中弹。

【问题讨论】:

  • 生成的 JSON 输出是什么样的?
  • 你得到什么错误?你可以在控制台中检查吗?
  • 2:9393/:197Uncaught SyntaxError: Unexpected token ILLEGAL
  • 嗯,根据 jsonlint.com,ruby 输出是有效的 JSON
  • Ruby json 示例末尾没有分号,但这可能只是类型/复制过去错误。

标签: php javascript jquery ruby json


【解决方案1】:

都是关于那些反斜杠的。

在 JSON 中出现&lt;/title&gt; 之类的任何地方,它实际上必须是&lt;\/title&gt;

问题是.to_json 没有添加那些反斜杠。

我们怎样才能做到?

【讨论】:

  • 你可以"...".to_json.gsub('&lt;/', '&lt;\/') (不是说单引号在这里很重要。
  • 是正斜杠 - 不需要转义吗?
  • 否,因为在 ruby​​ "\/" == "/" 中。单引号将是一个不同的故事。
  • 请注意,只有在将 JSON 注入嵌入 HTML 的 JavaScript 时,才需要对它们进行转义。结束标签终止脚本(理论上对于大多数脚本来说,肯定是&lt;/script&gt;)。
【解决方案2】:

这可能有点矫枉过正,但是当我使用 to_json 与 Rails 一起工作时,我讨厌它并找到了 RABL https://github.com/nesquena/rabl

你应该看看它。

【讨论】:

    【解决方案3】:

    我认为问题不在于 json 不是 json(json 字符串中的 / 没有问题),而是您在 html 文档中,因此像 &lt;/ 这样的字符具有特殊意义。

    我猜想 HTML 解析器认为这是关闭文档中实际正文标记的狡猾尝试。如果用 CDATA 部分将 json 括起来,即

    <script type="text/javascript">
    //<![CDATA[
      <%= get_templates %>
    //]]>
    </script>
    

    然后 HTML 解析器将知道不这样做。 Sinatra 中可能已经有帮手可以做到这一点

    【讨论】:

    • 这将阻止 XML 解析器将标签视为标签,但这无济于事,除非它是作为 application/xhtml+xml 提供的 XHTML 文档。市场上大多数 HTML 解析器不支持显式 CDATA 块。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多