Source code for thorn.utils.json
"""Json serialization utilities."""
from __future__ import absolute_import, unicode_literals
import datetime
import decimal
import uuid
from six import text_type
from celery.utils.imports import symbol_by_name
try:
from django.utils.functional import Promise as DjangoPromise
except ImportError: # pragma: no cover
class DjangoPromise(object): # noqa
pass
__all__ = ['JsonEncoder', 'dumps']
_JSON_EXTRA_ARGS = {
'simplejson': {'use_decimal': False},
}
def get_best_json(attr=None,
choices=['simplejson', 'json']):
for i, module in enumerate(choices):
try:
sym = ':'.join([module, attr]) if attr else module
return symbol_by_name(sym), _JSON_EXTRA_ARGS.get(module, {})
except (AttributeError, ImportError):
if i + 1 >= len(choices):
raise
json, _json_args = get_best_json()
[docs]class JsonEncoder(get_best_json('JSONEncoder')[0]):
"""Thorn custom Json encoder.
Notes:
Same as django.core.serializers.json.JSONEncoder but preserves
datetime microsecond information.
"""
[docs] def default(self, o,
dates=(datetime.datetime, datetime.date),
times=(datetime.time,),
textual=(decimal.Decimal, uuid.UUID, DjangoPromise),
isinstance=isinstance,
datetime=datetime.datetime,
text_type=text_type):
if isinstance(o, dates):
if not isinstance(o, datetime):
o = datetime(o.year, o.month, o.day, 0, 0, 0, 0)
r = o.isoformat()
if r.endswith("+00:00"):
r = r[:-6] + "Z"
return r
elif isinstance(o, times):
return o.isoformat()
elif isinstance(o, textual):
return text_type(o)
else:
return super(JsonEncoder, self).default(o)
[docs]def dumps(obj, encode=json.dumps, cls=JsonEncoder):
"""Serialize object as json string."""
return encode(obj, cls=cls, **_json_args)