Skip to content

Instantly share code, notes, and snippets.

@jlumpe
Created June 29, 2017 19:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jlumpe/f3ee9e61e132d3dfdea1151a796f49dc to your computer and use it in GitHub Desktop.
Save jlumpe/f3ee9e61e132d3dfdea1151a796f49dc to your computer and use it in GitHub Desktop.
Python JSON encoder that makes more of an effort to encode non-builtin types
from json import JSONEncoder
from numbers import Integral, Real
from collections.abc import Sequence, Mapping
class BetterJSONEncoder(JSONEncoder):
"""JSON encoder that makes more of an effort to encode non-builtin types."""
def default(self, o):
# Check bool subclasses first, as they are also considered integers.
if isinstance(o, bool):
return bool(o)
# Check numeric ABCs, most specific first
if isinstance(o, Integral):
return int(o)
if isinstance(o, Real):
return float(o)
# Check sequence and mapping ABCs
if isinstance(o, Sequence):
return list(o)
if isinstance(o, Mapping):
return dict(o)
# Subclass of plain old str. Probably disjoint from all other
# possibilities here.
if isinstance(o, str):
return str(o)
# Sequence protocol
# Check before __index__, Numpy arrays don't subclass Sequence and
# have an __index__ method (which raises an error on array with more
# than one element).
if hasattr(o, '__len__') and hasattr(o, '__getitem__'):
return list(o)
# Presence of this method indicates the object is an integer (according
# to the standard, but Numpy arrays don't obey this).
if hasattr(o, '__index__'):
return int(o)
# Both float and int types have both of the following methods, so in the
# absence of the __index__ method prioritize __float__.
if hasattr(o, '__float__'):
return float(o)
if hasattr(o, '__int__'):
return int(o)
return super().default(o)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment