thorn.utils.json — Thorn 1.3.0 documentation

# Source code for thorn.utils.json

    """

        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()

    class JsonEncoder(get_best_json('JSONEncoder')[0]):
        # like django.core.serializers.json.JSONEncoder but preserves
        # datetime microsecond information.

        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)

    def dumps(obj, encode=json.dumps, cls=JsonEncoder):
        return encode(obj, cls=cls, **_json_args)