diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py
index 5ccef380487..13070b303bd 100644
--- a/django/template/defaultfilters.py
+++ b/django/template/defaultfilters.py
@@ -83,10 +83,10 @@ def escapejs_filter(value):
@register.filter(is_safe=True)
-def json_script(value, element_id):
+def json_script(value, element_id=None):
"""
Output value JSON-encoded, wrapped in a ',
- element_id, mark_safe(json_str)
- )
+ if element_id:
+ template = ''
+ args = (element_id, mark_safe(json_str))
+ else:
+ template = ''
+ args = (mark_safe(json_str),)
+ return format_html(template, *args)
def conditional_escape(text):
diff --git a/docs/ref/templates/builtins.txt b/docs/ref/templates/builtins.txt
index 2edfd65c7b1..f02a8f61c86 100644
--- a/docs/ref/templates/builtins.txt
+++ b/docs/ref/templates/builtins.txt
@@ -1832,7 +1832,7 @@ If ``value`` is the list ``['a', 'b', 'c']``, the output will be the string
Safely outputs a Python object as JSON, wrapped in a ``'
)
+
+ @setup({'json-tag02': '{{ value|json_script }}'})
+ def test_without_id(self):
+ output = self.engine.render_to_string('json-tag02', {'value': {}})
+ self.assertEqual(output, '')
diff --git a/tests/utils_tests/test_html.py b/tests/utils_tests/test_html.py
index 909620ea3f1..63644daf615 100644
--- a/tests/utils_tests/test_html.py
+++ b/tests/utils_tests/test_html.py
@@ -173,6 +173,12 @@ class TestUtilsHtml(SimpleTestCase):
with self.subTest(arg=arg):
self.assertEqual(json_script(arg, 'test_id'), expected)
+ def test_json_script_without_id(self):
+ self.assertHTMLEqual(
+ json_script({'key': 'value'}),
+ '',
+ )
+
def test_smart_urlquote(self):
items = (
('http://öäü.com/', 'http://xn--4ca9at.com/'),