3

I have a Python dictionary where the keys are strings, and values are list of MyObject objects. If I execute

simplejson.dumps(dict)

it throws "MyObject not JSON serializable".

How can I avoid this exception, and how can I make MyObject serializable?

Stew
  • 4,495
  • 6
  • 31
  • 41
Giovanni Bitliner
  • 2,032
  • 5
  • 31
  • 50

1 Answers1

8

Proper Answer

In order to make your MyObject serializable, you need to implement a method that you can reference on dumps. For example:

class MyObject:
    #    ...
    #    MyObject has 3 properties: name (a string), number (an int), and parent (a MyObject)
    @staticmethod
    def serialize(obj):
        return {
            "name":   obj.name,
            "number": obj.number,
            "parent": obj.parent
        }

    #    ...

simplejson.dumps(myObjInstance, default=MyObject.serialize)

The cool thing is that dumps will, like every other JSON-serializable object, call the serialization method recursively. That is, obj.parent will get serialized as well, without any further action from you.

Golf'd Version

If all you want to do is 1-1 map instance variable names to their respective values, you can use some built-in Python magic. Whenever you want to serialize a more complex object (again, only using a 1-1 variable-value map), just call this line:

simplejson.dumps(anyObj, default=lambda obj: obj.__dict__)

For the given instance of MyObject, it will behave identically to the aforementioned serialize method.

Community
  • 1
  • 1
Patrick Perini
  • 22,555
  • 12
  • 59
  • 88
  • 5
    consider `operator.attrgetter('__dict__')` instead of using a lambda. – SingleNegationElimination May 11 '12 at 02:51
  • 1
    @SingleNegationElimination could you indicate why we should prefer that over a lambda? – Stew Feb 10 '16 at 18:22
  • 2
    @Stew: `operator.attrgetter()` is implemented in C; the `lambda` version will need to create new call frames, execute python bytecodes, and altogether do a bunch of work. When there's no concise, built in way to do it, a `lambda` is fine, but when there's something as concise and exact as the members of the `operator` module are available, those are better. – SingleNegationElimination Feb 10 '16 at 21:14