Neil
Neil

Reputation: 3281

Python/Django escape list of strings for JSON parsing by Javascript

Know these questions are annoying but I'm really stuck so would appreciate help. I'm trying to send a list of strings to the frontend and load into a javascript object. Relevant parts of the Django application:

In views.py in the handler function:

import json
def home(request):
    test_list = ["(hello world\")"]
    return render(request, 'app/home.html', {"test_list": json.dumps(test_list)})

In home.html:

let parsed = JSON.parse('{{test_list|safe}}');

I get the error:

Uncaught SyntaxError: Unexpected token ) in JSON at position 15

Things I have tried:

- running json.dumps directly on each (str) element of the list, not just on the whole list.

- Manually adding a backslash to each of (", ', (, ), [, ] )

- Manually adding two backslashes to each of (", ', (, ), [, ] )

- Not using |safe in the template

What has worked is just removing each of (", ', (, ), [, ] ). But I can't have them removed. I need them escaped.

Here is what Google Chrome tells me the template resolves to at the line that fails:

let parsed = JSON.parse('["(hello world\")"]');

Help much appreciated.

Upvotes: 0

Views: 1020

Answers (2)

Neil
Neil

Reputation: 3281

After another full day of research I've come up with a very elegant solution that appears to work for all cases.

Basically, the Python json module is capable of encoding and decoding properly. So what was required was not to mess with that, but rather to figure out how best to maintain it's results when pushing to the frontend.

What I then realised is that certain escape characters where obviously being "resolved" somewhere (I still do know know where or how exactly). The trick to preventing this is to call repr on the output of json.dumps

So the working code now is:

import json
def home(request):
    test_list = ["(hello world\")"]
    return render(request, 'app/home.html', {"test_list": repr(json.dumps(test_list))})

and

let parsed = JSON.parse({{test_list|safe}});

The two changes are adding repr in the views file, and removing the ' from the start and end of {{test_list|safe}} in the template (python's json handles that as well)

Upvotes: 0

user2314737
user2314737

Reputation: 29307

If you define

str = "(hello world\")";

then JSON.parse(str); will give an error (Unexpected token ( in JSON at position 0) because there is no JSON object starting with a ( (see MDN: full JSON syntax)

In order to have parentheses in your string you need to create a string that contains them using double quotes (since JSON accepts only double quotes).

If the enclosing quotes are double you need to escape the nested double quotes, see the snippet below:

// using double quotes outside: need escaping for the inner double quotes to avoid confusion
str = "\"(hello world)\"";
console.log(JSON.parse(str));

// using single quotes outside: no need to escape
str = '"(hello world)"';
console.log(JSON.parse(str));

Upvotes: 1

Related Questions