Show More
ext_json.py
95 lines
| 2.7 KiB
| text/x-python
|
PythonLexer
r1 | import datetime | |||
import decimal | ||||
import functools | ||||
r5073 | import json as stdlib_json | |||
r5012 | ||||
r5073 | try: | |||
# we keep simplejson for having dump functionality still | ||||
# orjson doesn't support it | ||||
import simplejson as sjson | ||||
except ImportError: | ||||
sjson = stdlib_json | ||||
try: | ||||
import orjson | ||||
import orjson as json | ||||
except ImportError: | ||||
json = stdlib_json | ||||
r1 | ||||
from rhodecode.lib.datelib import is_aware | ||||
r4972 | from rhodecode.lib.str_utils import safe_str | |||
r1 | ||||
try: | ||||
r2351 | import rhodecode.translation | |||
r1 | except ImportError: | |||
r2351 | rhodecode = None | |||
r1 | ||||
__all__ = ['json'] | ||||
def _obj_dump(obj): | ||||
""" | ||||
Custom function for dumping objects to JSON, if obj has __json__ attribute | ||||
or method defined it will be used for serialization | ||||
:param obj: | ||||
""" | ||||
r5073 | ||||
if isinstance(obj, set): | ||||
return list(obj) | ||||
r1 | # See "Date Time String Format" in the ECMA-262 specification. | |||
# some code borrowed from django 1.4 | ||||
elif isinstance(obj, datetime.datetime): | ||||
r = obj.isoformat() | ||||
r4935 | if isinstance(obj.microsecond, int): | |||
r1 | r = r[:23] + r[26:] | |||
if r.endswith('+00:00'): | ||||
r = r[:-6] + 'Z' | ||||
return r | ||||
elif isinstance(obj, datetime.date): | ||||
return obj.isoformat() | ||||
r5073 | elif isinstance(obj, decimal.Decimal): | |||
return str(obj) | ||||
r1 | elif isinstance(obj, datetime.time): | |||
if is_aware(obj): | ||||
raise TypeError("Time-zone aware times are not JSON serializable") | ||||
r = obj.isoformat() | ||||
r4935 | if isinstance(obj.microsecond, int): | |||
r1 | r = r[:12] | |||
return r | ||||
elif hasattr(obj, '__json__'): | ||||
if callable(obj.__json__): | ||||
return obj.__json__() | ||||
else: | ||||
return obj.__json__ | ||||
elif isinstance(obj, complex): | ||||
return [obj.real, obj.imag] | ||||
r2358 | elif rhodecode and isinstance(obj, rhodecode.translation._LazyString): | |||
r1 | return obj.eval() | |||
else: | ||||
raise TypeError(repr(obj) + " is not JSON serializable") | ||||
r5012 | sjson.dumps = functools.partial(sjson.dumps, default=_obj_dump) | |||
sjson.dump = functools.partial(sjson.dump, default=_obj_dump) | ||||
r4972 | json.dumps = functools.partial(json.dumps, default=_obj_dump, option=orjson.OPT_NON_STR_KEYS) | |||
r5012 | json.dump = functools.partial(sjson.dump, default=_obj_dump) | |||
r4972 | ||||
def formatted_json(*args, **kwargs): | ||||
# alias for formatted json | ||||
opts = orjson.OPT_NON_STR_KEYS | orjson.OPT_INDENT_2 | orjson.OPT_SORT_KEYS | ||||
return functools.partial(json.dumps, option=opts)(*args, **kwargs) | ||||
r1 | ||||
r4972 | def formatted_str_json(*args, **kwargs): | |||
opts = orjson.OPT_NON_STR_KEYS | orjson.OPT_INDENT_2 | orjson.OPT_SORT_KEYS | ||||
closure = functools.partial(json.dumps, option=opts) | ||||
return safe_str(closure(*args, **kwargs)) | ||||
def str_json(*args, **kwargs): | ||||
closure = functools.partial(json.dumps) | ||||
return safe_str(closure(*args, **kwargs)) | ||||