I am making an Encoder for converting python objects to json and when researching I see a lot of solutions that include a default
method. I'm not an expert in Python, but definitely not a novice either, and I'm wondering if I somehow missed that there is a default
method that gets run automatically when a class is called. Or, is this just because I have inherited from the JSONEcoder
class (which has a default method, and I am now just overriding)? Can someone clarify? And if so, is it basically the same as the
__init__()
method?
By the way, my encoder looks like this if you need more of a visual:
class ComplexEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, my_custom_object):
return str(obj)
return json.JSONEncoder.default(self, obj)
JSONEncoder
has a default
method which gets called if it doesn't know how to coerce a particular object into valid JSON. The default implementation just raises TypeError
(because it doesn't know how to coerce the type). However, when you override the default method, you have a chance to return an object that the encoder does know how to handle. If you don't know how to handle the type that is input (e.g. it isn't an instance of my_custom_type
), then you should either raise TypeError
yourself, or call the default
method on JSONencoder
so that it can raise the error.
Frequently, you'll see super
used here for cooperative inheritance:
class ComplexEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, my_custom_object):
return str(obj)
return super(ComplexEncoder, self).default(obj)
If all the encoder classes you build are of this form, you can mix them together:
class MySuperEncoder(ComplexEncoder, WidgetEncoder, FooEncoder):
pass
Now ComplexEncoder
will handle the things it knows about (e.g. my_custom_object
), WidgetEncoder
will encode the things that it knows how to handle (probably Widget
instances), and so forth.
Runnning dir(JSONEncoder)
gives us:
['__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattribute__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'default', # We found our method, let's see what it does
'encode',
'item_separator',
'iterencode',
'key_separator']
Running help(JSONEncoder.default)
gives us:
default(self, o) unbound json.encoder.JSONEncoder method
Implement this method in a subclass such that it returns
a serializable object for ``o``, or calls the base implementation
(to raise a ``TypeError``).
For example, to support arbitrary iterators, you could
implement default like this::
def default(self, o):
try:
iterable = iter(o)
except TypeError:
pass
else:
return list(iterable)
# Let the base class default method raise the TypeError
return JSONEncoder.default(self, o)
So it would seem it's designed this way for you to write your own should you subclass this object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With