71

Possible Duplicate:
Python serializable objects json

I need to know how to convert a dynamic python object into JSON. The object must be able to have multiple levels object child objects. For example:

class C(): pass
class D(): pass

c = C()
c.dynProperty1 = "something"
c.dynProperty2 = { 1, 3, 5, 7, 9 }
c.d = D()
c.d.dynProperty3 = "d.something"

# ... convert c to json ...

Using python 2.6 the following code:

import json

class C(): pass
class D(): pass

c = C()
c.what = "now?"
c.now = "what?"
c.d = D()
c.d.what = "d.what"

json.dumps(c.__dict__)

yields the following error:

TypeError: <__main__.D instance at 0x99237ec> is not JSON serializable

I don't know what types of subobjects a user might put into c. Is there a solution that is smart enough to detect if an attribute is an object and parse it's __dict__ automatically?

UPDATED to include subobjects on c.

Community
  • 1
  • 1
Trevor
  • 11,966
  • 11
  • 74
  • 94
  • except for the dynamic element--I don't know what properties might be added to the object before it is serialized into json. – Trevor Sep 13 '11 at 21:34
  • You'll notice the solution of the duplicate works in your case, too. – phihag Sep 13 '11 at 21:45
  • @phihag: thanks for pointing that out. It helped me realize there was more to my question than I thought (see updated question). – Trevor Sep 13 '11 at 22:05
  • Then you should probably ask a new question. Pay special notice not to include invalid example code. For example, you want `class C(object): pass`. I added an answer that should solve your problem. – phihag Sep 13 '11 at 22:56
  • First, thank you for the answer. I think that should do the trick. However, I'm a little confused. I don't see how "class C(): pass" is invalid code. Am I missing something? I am fairly new to Python. – Trevor Sep 14 '11 at 00:25
  • 2
    Oops sorry, I was totally wrong. `class C(): pass` is of course *valid*, but it creates an old-style class (just like `class C: pass` would) in Python 2.x. old-style classes are strange beasts. By inheriting from `object`, you get the saner new-style behaviour. – phihag Sep 14 '11 at 08:11

4 Answers4

133

Specify the default= parameter (doc):

json.dumps(c, default=lambda o: o.__dict__)
phihag
  • 245,801
  • 63
  • 407
  • 443
  • 6
    One of my object's attributes is a datetime and i'm having `'AttributeError' object has no attribute '__dict__'` – bachr Sep 07 '14 at 13:16
  • Same problem when an attribute is a set. – arun May 28 '15 at 19:41
  • 1
    @arun For a set, you'd use a different method. If you expect both objects and set, use a helper function instead of a lambda, test for `isinstance(o, set)` and then return something like `list(o)`. – phihag May 29 '15 at 05:23
  • 1
    This one workds better than `json.dumps(c.__dict__)`, why? – soulmachine Oct 11 '16 at 01:02
  • 5
    @soulmachine your code just dumps a dictionary, whose values (and values of values, recursively) may still be Python objects that have no JSON representation. The code in this answer uses the object's `__dict__` for all those problematic objects, recursively. – phihag Oct 11 '16 at 01:06
  • 2
    @soulmachine From the Python3 [documentation](https://docs.python.org/3/library/json.html#json.dump): *If specified, default should be a function that gets called for objects that can’t otherwise be serialized. It should return a JSON encodable version of the object or raise a TypeError. If not specified, TypeError is raised.* – MarAja Dec 02 '16 at 17:15
  • what's `o` object? – Benyamin Jafari Jul 12 '18 at 22:08
  • 1
    @BenyaminJafari `o` is the argument of the callback function. This callback function gets called for objects that can't be serialized by `json.dumps`, i.e. anything but `int`/`float`/`bool`/`str`/`dict`/`list`/`None`. – phihag Jul 13 '18 at 05:51
16
json.dumps(c.__dict__)

That will give you a generic JSON object, if that's what you're going for.

Austin Marshall
  • 2,661
  • 12
  • 14
9

Try using this package python-jsonpickle

Python library for serializing any arbitrary object graph into JSON. It can take almost any Python object and turn the object into JSON. Additionally, it can reconstitute the object back into Python.

funkotron
  • 407
  • 3
  • 14
0

json.dumps expects a dictonary as a parameter. For an instance c, the attribute c.__dict__ is a dictionary mapping attribute names to the corresponding objects.

rocksportrocker
  • 6,639
  • 2
  • 28
  • 46