1# -*- coding: utf-8 -*- 2""" 3 webapp2_extras.json 4 =================== 5 6 JSON helpers for webapp2. 7 8 :copyright: 2011 by tipfy.org. 9 :license: Apache Sotware License, see LICENSE for details. 10""" 11from __future__ import absolute_import 12 13import base64 14import urllib 15 16try: 17 # Preference for installed library with updated fixes. 18 # Also available in Google App Engine SDK >= 1.4.2. 19 import simplejson as json 20except ImportError: # pragma: no cover 21 try: 22 # Standard library module in Python >= 2.6. 23 import json 24 except ImportError: # pragma: no cover 25 raise RuntimeError( 26 'A JSON parser is required, e.g., simplejson at ' 27 'http://pypi.python.org/pypi/simplejson/') 28 29assert hasattr(json, 'loads') and hasattr(json, 'dumps'), \ 30 'Expected a JSON module with the functions loads() and dumps().' 31 32 33def encode(value, *args, **kwargs): 34 """Serializes a value to JSON. 35 36 This comes from `Tornado`_. 37 38 :param value: 39 A value to be serialized. 40 :param args: 41 Extra arguments to be passed to `json.dumps()`. 42 :param kwargs: 43 Extra keyword arguments to be passed to `json.dumps()`. 44 :returns: 45 The serialized value. 46 """ 47 # By default encode using a compact format. 48 kwargs.setdefault('separators', (',', ':')) 49 # JSON permits but does not require forward slashes to be escaped. 50 # This is useful when json data is emitted in a <script> tag 51 # in HTML, as it prevents </script> tags from prematurely terminating 52 # the javascript. Some json libraries do this escaping by default, 53 # although python's standard library does not, so we do it here. 54 # See: http://goo.gl/WsXwv 55 return json.dumps(value, *args, **kwargs).replace("</", "<\\/") 56 57 58def decode(value, *args, **kwargs): 59 """Deserializes a value from JSON. 60 61 This comes from `Tornado`_. 62 63 :param value: 64 A value to be deserialized. 65 :param args: 66 Extra arguments to be passed to `json.loads()`. 67 :param kwargs: 68 Extra keyword arguments to be passed to `json.loads()`. 69 :returns: 70 The deserialized value. 71 """ 72 if isinstance(value, str): 73 value = value.decode('utf-8') 74 75 assert isinstance(value, unicode) 76 return json.loads(value, *args, **kwargs) 77 78 79def b64encode(value, *args, **kwargs): 80 """Serializes a value to JSON and encodes it using base64. 81 82 Parameters and return value are the same from :func:`encode`. 83 """ 84 return base64.b64encode(encode(value, *args, **kwargs)) 85 86 87def b64decode(value, *args, **kwargs): 88 """Decodes a value using base64 and deserializes it from JSON. 89 90 Parameters and return value are the same from :func:`decode`. 91 """ 92 return decode(base64.b64decode(value), *args, **kwargs) 93 94 95def quote(value, *args, **kwargs): 96 """Serializes a value to JSON and encodes it using urllib.quote. 97 98 Parameters and return value are the same from :func:`encode`. 99 """ 100 return urllib.quote(encode(value, *args, **kwargs)) 101 102 103def unquote(value, *args, **kwargs): 104 """Decodes a value using urllib.unquote and deserializes it from JSON. 105 106 Parameters and return value are the same from :func:`decode`. 107 """ 108 return decode(urllib.unquote(value), *args, **kwargs) 109