Convert dynamic python object to json [duplicate]
Asked Answered
B

4

77

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 ...

I tried this 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__)

but I got an error that says TypeError: <__main__.D instance at 0x99237ec> is not JSON serializable.

How can I make it so that any sub-objects that are classes are automatically serialized using their __dict__?

Bitternut answered 13/9, 2011 at 21:18 Comment(6)
except for the dynamic element--I don't know what properties might be added to the object before it is serialized into json.Bitternut
You'll notice the solution of the duplicate works in your case, too.Rimma
@phihag: thanks for pointing that out. It helped me realize there was more to my question than I thought (see updated question).Bitternut
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.Rimma
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.Bitternut
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.Rimma
R
144

Specify the default= parameter (doc):

json.dumps(c, default=lambda o: o.__dict__)
Rimma answered 13/9, 2011 at 22:59 Comment(8)
One of my object's attributes is a datetime and i'm having 'AttributeError' object has no attribute '__dict__'Topotype
Same problem when an attribute is a set.Raycher
@Raycher 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).Rimma
This one workds better than json.dumps(c.__dict__), why?Ambitendency
@Ambitendency 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.Rimma
@Ambitendency From the Python3 documentation: 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.Negativism
what's o object?Exorable
@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.Rimma
K
16
json.dumps(c.__dict__)

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

Keheley answered 13/9, 2011 at 21:24 Comment(2)
After looking into phihag's comment, I did some further testing and realized that this solution does not work in all cases...updating question...Bitternut
That works for me as well.Milldam
I
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.

Impanel answered 13/9, 2011 at 21:34 Comment(0)
D
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.

Dmitri answered 13/9, 2011 at 21:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.