Why Doesn't Jsonencoder Work For Namedtuples?
Solution 1:
As I said in a comment, the json.JSONEncoder
only calls default
when it encounters an object type it doesn't already know how to serialize itself. There's a table of them in the json
documentation. Here's a screenshot of it for easy reference:
Note that tuple
is on the list, and since namedtuple
is a subclasses of tuple
, it applies to them, too. (i.e. because isinstance(friend_instance, tuple)
→ True
).
This is why your code for handling instances of the Friend
class never gets called.
Below is one workaround — namely by creating a simple Wrapper
class whose instances won't be a type that the json.JSONEncoder
thinks it already knows how to handle, and then specifying a default=
keyword argument function that's to be called whenever an object is encountered that it doesn't already know how to do.
Here's what I mean:
import json
from collections import namedtuple
classWrapper(object):
""" Container class for objects with an _asdict() method. """def__init__(self, obj):
asserthasattr(obj, '_asdict'), 'Cannot wrap object with no _asdict method'
self.obj = obj
if __name__ == '__main__':
Friend = namedtuple("Friend", ["id", 'f_name', 'l_name'])
t = Friend(21, 'Steve', 'Rogerson')
print(t)
print(json.dumps(t))
print(json.dumps(Wrapper(t), default=lambda wrapper: wrapper.obj._asdict()))
Output:
Friend(id=21, f_name='Steve', l_name='Rogerson')
[21, "Steve", "Rogerson"]
{"id": 21, "f_name": "Steve", "l_name": "Rogerson"}
For some additional information and insights, also check out my answer to the related question Making object JSON serializable with regular encoder.
Post a Comment for "Why Doesn't Jsonencoder Work For Namedtuples?"