in HTML document?", "text": "<p>In a Rails 3.1 app, how can I safely embed some JSON data into an HTML document?</p> <p>Suppose I have this in a controller action:</p> <pre class="prettyprint"><code>@tags = [ {name:"tag1", color:"green"}, {name:"&lt;/script&gt;&lt;b&gt;I can do something bad here&lt;/b&gt;", color:"red"} ] </code></pre> <p>And this in a corresponding view:</p> <pre class="prettyprint"><code>&lt;script type="text/javascript" charset="utf-8"&gt; //&lt;![CDATA[ var tags_list = &lt;%= @tags.to_json %&gt;; // ]]&gt; &lt;/script&gt; </code></pre> <p>Then I get this in resulting HTML:</p> <pre class="prettyprint"><code>var tags_list = [ {&amp;quot;name&amp;quot;:&amp;quot;tag1&amp;quot;,&amp;quot;color&amp;quot;:&amp;quot;green&amp;quot;}, {&amp;quot;name&amp;quot;:&amp;quot;&amp;lt;/script&amp;gt;&amp;lt;b&amp;gt;I can do something bad here&amp;lt;/b&amp;gt;&amp;quot;,&amp;quot;color&amp;quot;:&amp;quot;red&amp;quot;} ]; </code></pre> <p>which triggers a <code>SyntaxError: Unexpected token &amp;</code> in Chrome</p> <p>If I remove the Rails' default HTML escaping with <code>&lt;%=raw tags.to_json %&gt;</code>, then it returns this:</p> <pre class="prettyprint"><code>var tags_list = [ {"name":"tag1","color":"green"}, {"name":"&lt;/script&gt;&lt;b&gt;I can do something bad here&lt;/b&gt;","color":"red"} ]; </code></pre> <p>which, of course, breaks the HTML document with <code>&lt;/script&gt;</code>.</p> <p>Can I somehow tell to_json() method to return something more like this:</p> <pre class="prettyprint"><code>var tags_list = [ {"name":"tag1","color":"green"}, {"name":"&amp;lt;/script&amp;gt;&amp;lt;b&amp;gt;I can do something bad here&amp;lt;/b&amp;gt;","color":"red"} ]; </code></pre> <p>I asked this question on rubyonrails-talk mailing list, and I understand now that some people think that's a very bad idea to begin with, but in my case it works very nicely, as long as there are no HTML special chars in the data. So I just want to make the string returned by <code>to_json</code> HTML safe and still have JavaScript parse it properly.</p> <p><strong>UPDATE:</strong> Based on @coreyward comment, I did make it a JS string literal, and that seems to be working great now. Its not quite as elegant of a solution as I was hoping for, but its not too bad either. Here is the code that is working for me:</p> <pre class="prettyprint"><code>&lt;% tags = [{name:"tag1", color:"green"}, {name:"&lt;/script&gt;&lt;b&gt;I can \\n\\ndo something bad here&lt;/b&gt;", color:"red"}] %&gt; &lt;script type="text/javascript" charset="utf-8"&gt; //&lt;![CDATA[ var tags_list = $.parseJSON('&lt;%=j tags.to_json.html_safe %&gt;'); // ]]&gt; &lt;/script&gt; </code></pre> <p>which results in:</p> <pre class="prettyprint"><code>&lt;script type="text/javascript" charset="utf-8"&gt; //&lt;![CDATA[ var tags_list = $.parseJSON('[{\\"name\\":\\"tag1\\",\\"color\\":\\"green\\"},{\\"name\\":\\"&lt;\\/script&gt;&lt;b&gt;I can \\\\n\\\\ndo something bad here&lt;\\/b&gt;\\",\\"color\\":\\"red\\"}]'); // ]]&gt; &lt;/script&gt; </code></pre>", "answerCount": 1, "upvoteCount": 457, "dateCreated": "2011-08-26 14:08:33", "dateModified": "2022-10-24 04:13:41", "author": { "type": "Person", "name": "nnc" }, "acceptedAnswer": { "@type": "Answer", "text": "<p>Your code using just <code>@tags.to_json</code> works in rails3, <em>if</em> you enable it with:</p> <pre class="prettyprint"><code> ActiveSupport.escape_html_entities_in_json = true </code></pre> <p>Otherwise, your other option is this:</p> <pre class="prettyprint"><code> var tags_list = &lt;%= raw @tags.to_json.gsub("&lt;/", "&lt;\\\\/") %&gt;; </code></pre> <p>This saves the client having to parse the whole thing through $</p>", "upvoteCount": 147, "url": "https://exchangetuts.com/how-to-safely-embed-json-with-script-in-html-document-1639810629054982#answer-1648478241128574", "dateCreated": "2022-10-22 15:13:41", "dateModified": "2022-10-24 04:13:41", "author": { "type": "Person", "name": "Lawrence Pit" } } } }
Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to safely embed JSON with </script> in HTML document?

Tags:

In a Rails 3.1 app, how can I safely embed some JSON data into an HTML document?

Suppose I have this in a controller action:

@tags = [     {name:"tag1", color:"green"},      {name:"</script><b>I can do something bad here</b>", color:"red"} ] 

And this in a corresponding view:

<script type="text/javascript" charset="utf-8">     //<![CDATA[     var tags_list = <%= @tags.to_json %>;     // ]]> </script> 

Then I get this in resulting HTML:

var tags_list = [     {&quot;name&quot;:&quot;tag1&quot;,&quot;color&quot;:&quot;green&quot;},     {&quot;name&quot;:&quot;&lt;/script&gt;&lt;b&gt;I can do something bad here&lt;/b&gt;&quot;,&quot;color&quot;:&quot;red&quot;} ]; 

which triggers a SyntaxError: Unexpected token & in Chrome

If I remove the Rails' default HTML escaping with <%=raw tags.to_json %>, then it returns this:

var tags_list = [     {"name":"tag1","color":"green"},     {"name":"</script><b>I can do something bad here</b>","color":"red"} ]; 

which, of course, breaks the HTML document with </script>.

Can I somehow tell to_json() method to return something more like this:

var tags_list = [     {"name":"tag1","color":"green"},     {"name":"&lt;/script&gt;&lt;b&gt;I can do something bad here&lt;/b&gt;","color":"red"} ]; 

I asked this question on rubyonrails-talk mailing list, and I understand now that some people think that's a very bad idea to begin with, but in my case it works very nicely, as long as there are no HTML special chars in the data. So I just want to make the string returned by to_json HTML safe and still have JavaScript parse it properly.

UPDATE: Based on @coreyward comment, I did make it a JS string literal, and that seems to be working great now. Its not quite as elegant of a solution as I was hoping for, but its not too bad either. Here is the code that is working for me:

<% tags = [{name:"tag1", color:"green"}, {name:"</script><b>I can \n\ndo something bad here</b>", color:"red"}] %>  <script type="text/javascript" charset="utf-8">     //<![CDATA[     var tags_list = $.parseJSON('<%=j tags.to_json.html_safe %>');     // ]]> </script> 

which results in:

<script type="text/javascript" charset="utf-8">     //<![CDATA[     var tags_list = $.parseJSON('[{\"name\":\"tag1\",\"color\":\"green\"},{\"name\":\"<\/script><b>I can \\n\\ndo something bad here<\/b>\",\"color\":\"red\"}]');     // ]]> </script> 
like image 457
nnc Avatar asked Aug 26 '11 14:08

nnc


People also ask

Can you use JSON in HTML?

JSON can very easily be translated into JavaScript. JavaScript can be used to make HTML in your web pages.

Can you convert JSON to HTML?

The key function that enables us to convert JSON to HTML at runtime is JSON. parse() . The JSON. parse() method takes textual JSON data and converts it to a JavaScript object.

How read JSON data from HTML?

The jQuery code uses getJSON() method to fetch the data from the file's location using an AJAX HTTP GET request. It takes two arguments. One is the location of the JSON file and the other is the function containing the JSON data. The each() function is used to iterate through all the objects in the array.


1 Answers

Your code using just @tags.to_json works in rails3, if you enable it with:

   ActiveSupport.escape_html_entities_in_json = true 

Otherwise, your other option is this:

   var tags_list = <%= raw @tags.to_json.gsub("</", "<\\/") %>; 

This saves the client having to parse the whole thing through $

like image 147
Lawrence Pit Avatar answered Oct 24 '22 04:10

Lawrence Pit