0

Newbie here. I'm working with a database of apartment complexes and apartment units for an intro CS class and trying to build a web app using flask.

In application.py, I've got something like this:

locationdict = 

{
    "Complex A": [1, 2, 3],
    "Complex B": [4, 5, 6]
}

JSONlocationdict = json.dumps(locationdict, sort_keys=True)

return render_template("start.html", JSONlocationdict=JSONlocationdict)

But nothing seems to work when I'm trying to access that data from the dictionary in JavaScript. The HTML page looks roughly like this:


<button onclick = "getUnits(this)" id="Complex A"> Complex A </button>

<script>

    function getUnits(arg) {

         var locationName = arg.getAttribute("id");

         var JSONlocationdict = "{{ JSONlocationdict }}";

         console.log(JSONlocationdict)

//  In the console, this is what you see: 
//  {&#34;Complex A&#34;: [1,2,3], &#34;Complex B&#34;, [4,5,6]}

         var obj = JSON.parse(JSONlocationdict);

         console.log(obj); // this returns the error

//  Then you see this in the console:
//  Uncaught SyntaxError: Unexpected token & in JSON at position 1
//  at JSON.parse (<anonymous>)
//  at getUnits (start:88)
//  at HTMLButtonElement.onclick (start:119)

    var units = obj["Complex A"];

    console.log(units); 

// That last request to log to the console does nothing so far.

   }
</script>

I've tried using different ways to convert the original dictionary into JSON like jsonify and json.loads() instead of dumps(). I have gone through piles and piles of entries on stackoverflow about SyntaxError: Unexpected token, but I can't seem to get anything to work. Any ideas??

The only thing that seems to work reliably is having two separate pages -- the first page where the user can select from a list of apartment complexes and then sending them to a second page where they can then pick the unit.

It would be nice if they could click a button for the apartment complex, and then have the list of units available at that complex get dynamically generated on the same page, though.

  • Start by changing your line to `var JSONlocationdict = "{{ JSONlocationdict|safe }}";`. (This assumes you are using Jinja2 as your template engine). This will prevent the html entities from being replaced with escape sequences. – sberry Aug 18 '20 at 15:10
  • I should have made that `var JSONlocationdict = '{{ JSONlocationdict|safe }}';` so that json strings don't cause headaches. – sberry Aug 18 '20 at 15:29
  • This worked! Thank you!! – chasing_at_windmills Aug 18 '20 at 23:05

1 Answers1

0

The Flask method render_template turns your JSON into a string, as you can see by logging the JSONlocationdict. Since it's rendering the string to HTML, it escapes the double quote characters, which is what your JavaScript is having the issue parsing.

To solve this issue, you'll need to un-escape the JSONlocationdict before passing it to JSON.parse. There are many ways to accomplish this, the accepted answer here should work in your case if you want to do it in the browser.

function htmlDecode(input){
  var e = document.createElement('textarea');
  e.innerHTML = input;
  // handle case of empty input
  return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}

t = '{&#34;Complex A&#34;: [1,2,3], &#34;Complex B&#34;: [4,5,6]}'

x = htmlDecode(t)

console.log(JSON.parse(x))

Note: that in the above snippet, I had to edit the console.log response that was in your question to have the : after "Complex B" instead of the comma that was there.
If the result is actually what is in your question, then the JSON is not being formatted correctly by Flask, although your Flask code looks correct.

There are other ways that you can accomplish this task using AJAX and another Flask URL returning a jsonify response. There also are some template filters (like |safe) that do this, but depend on the template library you are using.

Matt Dale
  • 165
  • 1
  • 9
  • Ahh thank you! This explanation was so helpful! Someone mentioned the |safe filter, too, and that seemed to work, but the conversation and comments in the link you shared helped contextualized some of the possible security issues. Thank you again for your help with this!! I appreciate it. – chasing_at_windmills Aug 18 '20 at 23:11
  • I'm glad it was helpful! – Matt Dale Aug 19 '20 at 00:58