|
|
|
@ -30,69 +30,6 @@ _COMPOSED_ERROR_HANDLERS = frozenset((None, 'surrogate_or_replace',
|
|
|
|
|
'surrogate_then_replace'))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _json_encode_fallback(obj):
|
|
|
|
|
if isinstance(obj, Set):
|
|
|
|
|
return list(obj)
|
|
|
|
|
elif isinstance(obj, datetime.datetime):
|
|
|
|
|
return obj.isoformat()
|
|
|
|
|
raise TypeError("Cannot json serialize %s" % to_native(obj))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def jsonify(data, **kwargs):
|
|
|
|
|
for encoding in ("utf-8", "latin-1"):
|
|
|
|
|
try:
|
|
|
|
|
return json.dumps(data, encoding=encoding, default=_json_encode_fallback, **kwargs)
|
|
|
|
|
# Old systems using old simplejson module does not support encoding keyword.
|
|
|
|
|
except TypeError:
|
|
|
|
|
try:
|
|
|
|
|
new_data = container_to_text(data, encoding=encoding)
|
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
|
continue
|
|
|
|
|
return json.dumps(new_data, default=_json_encode_fallback, **kwargs)
|
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
|
continue
|
|
|
|
|
raise UnicodeError('Invalid unicode encoding encountered')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def container_to_bytes(d, encoding='utf-8', errors='surrogate_or_strict'):
|
|
|
|
|
''' Recursively convert dict keys and values to byte str
|
|
|
|
|
|
|
|
|
|
Specialized for json return because this only handles, lists, tuples,
|
|
|
|
|
and dict container types (the containers that the json module returns)
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
if isinstance(d, text_type):
|
|
|
|
|
return to_bytes(d, encoding=encoding, errors=errors)
|
|
|
|
|
elif isinstance(d, dict):
|
|
|
|
|
return dict(container_to_bytes(o, encoding, errors) for o in iteritems(d))
|
|
|
|
|
elif isinstance(d, list):
|
|
|
|
|
return [container_to_bytes(o, encoding, errors) for o in d]
|
|
|
|
|
elif isinstance(d, tuple):
|
|
|
|
|
return tuple(container_to_bytes(o, encoding, errors) for o in d)
|
|
|
|
|
else:
|
|
|
|
|
return d
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def container_to_text(d, encoding='utf-8', errors='surrogate_or_strict'):
|
|
|
|
|
"""Recursively convert dict keys and values to byte str
|
|
|
|
|
|
|
|
|
|
Specialized for json return because this only handles, lists, tuples,
|
|
|
|
|
and dict container types (the containers that the json module returns)
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if isinstance(d, binary_type):
|
|
|
|
|
# Warning, can traceback
|
|
|
|
|
return to_text(d, encoding=encoding, errors=errors)
|
|
|
|
|
elif isinstance(d, dict):
|
|
|
|
|
return dict(container_to_text(o, encoding, errors) for o in iteritems(d))
|
|
|
|
|
elif isinstance(d, list):
|
|
|
|
|
return [container_to_text(o, encoding, errors) for o in d]
|
|
|
|
|
elif isinstance(d, tuple):
|
|
|
|
|
return tuple(container_to_text(o, encoding, errors) for o in d)
|
|
|
|
|
else:
|
|
|
|
|
return d
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def to_bytes(obj, encoding='utf-8', errors=None, nonstring='simplerepr'):
|
|
|
|
|
"""Make sure that a string is a byte string
|
|
|
|
|
|
|
|
|
@ -320,3 +257,66 @@ if PY3:
|
|
|
|
|
to_native = to_text
|
|
|
|
|
else:
|
|
|
|
|
to_native = to_bytes
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _json_encode_fallback(obj):
|
|
|
|
|
if isinstance(obj, Set):
|
|
|
|
|
return list(obj)
|
|
|
|
|
elif isinstance(obj, datetime.datetime):
|
|
|
|
|
return obj.isoformat()
|
|
|
|
|
raise TypeError("Cannot json serialize %s" % to_native(obj))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def jsonify(data, **kwargs):
|
|
|
|
|
for encoding in ("utf-8", "latin-1"):
|
|
|
|
|
try:
|
|
|
|
|
return json.dumps(data, encoding=encoding, default=_json_encode_fallback, **kwargs)
|
|
|
|
|
# Old systems using old simplejson module does not support encoding keyword.
|
|
|
|
|
except TypeError:
|
|
|
|
|
try:
|
|
|
|
|
new_data = container_to_text(data, encoding=encoding)
|
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
|
continue
|
|
|
|
|
return json.dumps(new_data, default=_json_encode_fallback, **kwargs)
|
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
|
continue
|
|
|
|
|
raise UnicodeError('Invalid unicode encoding encountered')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def container_to_bytes(d, encoding='utf-8', errors='surrogate_or_strict'):
|
|
|
|
|
''' Recursively convert dict keys and values to byte str
|
|
|
|
|
|
|
|
|
|
Specialized for json return because this only handles, lists, tuples,
|
|
|
|
|
and dict container types (the containers that the json module returns)
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
if isinstance(d, text_type):
|
|
|
|
|
return to_bytes(d, encoding=encoding, errors=errors)
|
|
|
|
|
elif isinstance(d, dict):
|
|
|
|
|
return dict(container_to_bytes(o, encoding, errors) for o in iteritems(d))
|
|
|
|
|
elif isinstance(d, list):
|
|
|
|
|
return [container_to_bytes(o, encoding, errors) for o in d]
|
|
|
|
|
elif isinstance(d, tuple):
|
|
|
|
|
return tuple(container_to_bytes(o, encoding, errors) for o in d)
|
|
|
|
|
else:
|
|
|
|
|
return d
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def container_to_text(d, encoding='utf-8', errors='surrogate_or_strict'):
|
|
|
|
|
"""Recursively convert dict keys and values to byte str
|
|
|
|
|
|
|
|
|
|
Specialized for json return because this only handles, lists, tuples,
|
|
|
|
|
and dict container types (the containers that the json module returns)
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
if isinstance(d, binary_type):
|
|
|
|
|
# Warning, can traceback
|
|
|
|
|
return to_text(d, encoding=encoding, errors=errors)
|
|
|
|
|
elif isinstance(d, dict):
|
|
|
|
|
return dict(container_to_text(o, encoding, errors) for o in iteritems(d))
|
|
|
|
|
elif isinstance(d, list):
|
|
|
|
|
return [container_to_text(o, encoding, errors) for o in d]
|
|
|
|
|
elif isinstance(d, tuple):
|
|
|
|
|
return tuple(container_to_text(o, encoding, errors) for o in d)
|
|
|
|
|
else:
|
|
|
|
|
return d
|
|
|
|
|