Code

Ticket #17419: json-filter.v2.diff

File json-filter.v2.diff, 3.7 KB (added by carbonXT, 2 years ago)

json template filter with tests and docs - output no longer marked safe

Line 
1diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py
2index f93e799..06cf91c 100644
3--- a/django/template/defaultfilters.py
4+++ b/django/template/defaultfilters.py
5@@ -9,7 +9,7 @@ from pprint import pformat
6 
7 from django.template.base import Variable, Library, VariableDoesNotExist
8 from django.conf import settings
9-from django.utils import formats
10+from django.utils import formats, simplejson
11 from django.utils.dateformat import format, time_format
12 from django.utils.encoding import force_unicode, iri_to_uri
13 from django.utils.html import (conditional_escape, escapejs, fix_ampersands,
14@@ -838,6 +838,18 @@ def filesizeformat(bytes):
15         return ugettext("%s TB") % filesize_number_format(bytes / (1024 * 1024 * 1024 * 1024))
16     return ugettext("%s PB") % filesize_number_format(bytes / (1024 * 1024 * 1024 * 1024 * 1024))
17 
18+@register.filter(is_safe=True)
19+def json(value):
20+    """
21+    Returns the json representation of value.
22+
23+    Note that the HTML spec (though not XHTML) declares all text within
24+    <script> tags to be CDATA and therefore does not need escaping.
25+    Thus, when using this filter between <script> tags for such a document,
26+    you'll want to avoid escaping the output: {{ data|json|safe }}
27+    """
28+    return simplejson.dumps(value)
29+
30 @register.filter(is_safe=False)
31 def pluralize(value, arg=u's'):
32     """
33diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt
34index 85d43ce..3358791 100644
35--- a/docs/ref/templates/builtins.txt
36+++ b/docs/ref/templates/builtins.txt
37@@ -1665,6 +1665,34 @@ For example::
38 If ``value`` is the list ``['a', 'b', 'c']``, the output will be the string
39 ``"a // b // c"``.
40 
41+.. templatefilter:: json
42+
43+json
44+^^^^
45+
46+.. versionadded:: 1.4
47+
48+Coverts a python datastructure of possibly nested dictionaries and lists into
49+a json string.
50+
51+For example::
52+
53+    {{ value|json }}
54+
55+If ``value`` is the python dictionary with nested list
56+``{'hello': ['world', 'wide']}``, the output will be the string
57+``'{"hello": ["world", "wide"]}'``.
58+
59+This filter is most often used within ``<script>`` tags. Per the
60+HTML spec (though not XHTML) all text within ``<script>`` tags is
61+CDATA and therefore does not need escaping. Thus, when using this
62+filter in such a situation, you'll want to explicitly mark the output
63+as safe to avoid html-entity escaping. For example::
64+
65+    <script>
66+        var json_data = {{ value|json|safe }};
67+    </script>
68+
69 .. templatefilter:: last
70 
71 last
72diff --git a/tests/regressiontests/templates/filters.py b/tests/regressiontests/templates/filters.py
73index 54c1267..262304b 100644
74--- a/tests/regressiontests/templates/filters.py
75+++ b/tests/regressiontests/templates/filters.py
76@@ -106,6 +106,11 @@ def get_filter_tests():
77         'filter-lower01': ("{% autoescape off %}{{ a|lower }} {{ b|lower }}{% endautoescape %}", {"a": "Apple & banana", "b": mark_safe("Apple &amp; banana")}, u"apple & banana apple &amp; banana"),
78         'filter-lower02': ("{{ a|lower }} {{ b|lower }}", {"a": "Apple & banana", "b": mark_safe("Apple &amp; banana")}, u"apple &amp; banana apple &amp; banana"),
79 
80+        # json filter #17419
81+        'filter-json01': ("{{ data|json }}", {"data": {"hello": ["world", "universe"]}}, u'{&quot;hello&quot;: [&quot;world&quot;, &quot;universe&quot;]}'),
82+        'filter-json02': ("{{ data|json|safe }}", {"data": {"foo": "<bar>"}}, u'{"foo": "<bar>"}'),
83+        'filter-json03': ("{{ data|json|safe }}", {"data": ["foo", 'ba"r']}, u'["foo", "ba\\"r"]'),
84+
85         # The make_list filter can destroy existing escaping, so the results are
86         # escaped.
87         'filter-make_list01': ("{% autoescape off %}{{ a|make_list }}{% endautoescape %}", {"a": mark_safe("&")}, u"[u'&']"),