Merge pull request #2194 from leonelcamara/patch-31

Fixes #2182 possibly Fixes #2190
This commit is contained in:
mdipierro
2019-05-05 20:30:40 -07:00
committed by GitHub
2 changed files with 39 additions and 8 deletions

View File

@@ -119,13 +119,43 @@ def xml(value, encoding='UTF-8', key='document', quote=True):
return ('<?xml version="1.0" encoding="%s"?>' % encoding) + str(xml_rec(value, key, quote))
def json(value, default=custom_json, indent=None, sort_keys=False):
value = json_parser.dumps(value, default=default, sort_keys=sort_keys, indent=indent)
# replace JavaScript incompatible spacing
# http://timelessrepo.com/json-isnt-a-javascript-subset
# PY3 FIXME
# return value.replace(ur'\u2028', '\\u2028').replace(ur'\2029', '\\u2029')
return value
class JSONEncoderForHTML(json_parser.JSONEncoder):
"""An encoder that produces JSON safe to embed in HTML.
To embed JSON content in, say, a script tag on a web page, the
characters &, < and > should be escaped. They cannot be escaped
with the usual entities (e.g. &amp;) because they are not expanded
within <script> tags.
This class also escapes the line separator and paragraph separator
characters U+2028 and U+2029, irrespective of the ensure_ascii setting,
as these characters are not valid in JavaScript strings (see
http://timelessrepo.com/json-isnt-a-javascript-subset).
"""
def encode(self, o):
# Override JSONEncoder.encode because it has hacks for
# performance that make things more complicated.
chunks = self.iterencode(o, True)
if self.ensure_ascii:
return ''.join(chunks)
else:
return u''.join(chunks)
def iterencode(self, o, _one_shot=False):
chunks = super(JSONEncoderForHTML, self).iterencode(o, _one_shot)
for chunk in chunks:
chunk = chunk.replace('&', '\\u0026')
chunk = chunk.replace('<', '\\u003c')
chunk = chunk.replace('>', '\\u003e')
if not self.ensure_ascii:
chunk = chunk.replace(u'\u2028', '\\u2028')
chunk = chunk.replace(u'\u2029', '\\u2029')
yield chunk
def json(value, default=custom_json, indent=None, sort_keys=False, cls=JSONEncoderForHTML):
return json_parser.dumps(value, default=default, cls=cls, sort_keys=sort_keys, indent=indent)
def csv(value):
return ''

View File

@@ -50,7 +50,8 @@ class TestSerializers(unittest.TestCase):
lazy_translation = T('abc')
self.assertEqual(json(lazy_translation), u'"abc"')
# html helpers are xml()ed before too
self.assertEqual(json(SPAN('abc')), u'"<span>abc</span>"')
self.assertEqual(json(SPAN('abc'), cls=None), u'"<span>abc</span>"')
self.assertEqual(json(SPAN('abc')), u'"\\u003cspan\\u003eabc\\u003c/span\\u003e"')
# unicode keys make a difference with loads_json
base = {u'è': 1, 'b': 2}
base_enc = json(base)