Friday, March 14, 2014

Python Flask - passing JSON to a template in a variable

I ran into a problem in my Python Flask app. I wanted to store some JSON-formatted data in a Python variable, and use JQuery's parseJSON function to consume that data inside a Jinja template. When I tried to parse the JSON in the template, a JavaScript error resulted. I figured out why, and how to work around it.

By the way, the same problem occurs, and the same workaround applies, whether you pass the variable in the call to render_template, or use a session variable.

Here's a copy of my first attempt at the code...

Python:

def index():
        return render_template('viewer_type.html', myVar='{"abc": "123", "def": "456"}')

JavaScript:

<script src='jquery-1.10.0.min.js></script>
<script>
        var myVar = "{{ myVar }}";
        var myJSON = $.parseJSON(myVar);
        prompt("abc", myJSON.abc);
</script>

This failed. prompt never executed, and Chrome's JavaScript console reported this error.

Uncaught SyntaxError: Unexpected token &

I realized that the contents of the variable were being encoded when Flask passed them to the template. Adding this line of JavaScript...

prompt("myVar", myVar);

... revealed that my JSON had turned into:

{&#34;abc&#34;: &#34;123&#34;, &#34;def&#34;: &#34;456&#34;}

Thanks to this helpful post on stackoverflow, I found a convenient way to decode the encoded text in JavaScript. I encapsulated that in a function:

function decodeJSON(encodedJSON) {
            var decodedJSON = $('<div/>').html(encodedJSON).text();
            return $.parseJSON(decodedJSON);
}


Then I just needed to amend my original JavaScript to call decodeJSON, so the whole thing looks like this:

<script src='jquery-1.10.0.min.js></script>
<script>
 function decodeJSON(encodedJSON) {
  var decodedJSON = $('<div/>').html(encodedJSON).text();
  return $.parseJSON(decodedJSON);
 }


 var myVar = '{{ myVar }}';
 prompt('abc', decodeJSON(myVar).abc);
</script>


Success! The expected output, 123, was displayed, and there were no more errors in the JavaScript console.