Search code examples
pythonjsonserializationinner-classes

How to make a class with an inner class JSON serializable


I would like to automatically convert a Python class into a dictionary so I can convert it to JSON. The question How to make a class JSON serializable suggests to use myClass.__dict__, however, using this does not turn any inner classes into a JSON serializable object.

The following example...

class Thing():
    def __init__(self, name):
        self.name = name
        self.children = [self.Thing2(self)]

    class Thing2():
        def __init__(self, parent):
            self.name = parent.name + "'s child"

myThing = Thing("Clay")
print(myThing.__dict__)

yields the result...

{'name': 'Clay', 'children': [<__main__.Thing.Thing2 object at 0x00000257C4358B00>]}

which is still not JSON serializable. How do I convert a class AND INNER CLASSES into a JSON serializable object?


Solution

  • While myClass.__dict__ does not work on inner classes, you can define your own method to convert your class into a dictionary, as long as you know what fields are an Object.

    The follow example...

    class Thing():
        def __init__(self, name):
            self.name = name
            self.children = [self.Thing2(self)]
    
        def to_dict(self):
            dict = self.__dict__
            dict["children"] = [child.__dict__ for child in dict["children"]]
            return dict
    
    
        class Thing2():
            def __init__(self, parent):
                self.name = parent.name + "'s child"
    
    
    my_thing = Thing("Clay")
    print(my_thing.__dict__)
    print(my_thing.to_dict())
    

    yields the result...

    {'name': 'Clay', 'children': [<__main__.Thing.Thing2 object at 0x00000257C4358B00>]}
    {'name': 'Clay', 'children': [{'name': "Clay's child"}]}
    

    which can be converted into JSON using json.dumps().

    If you do not know what fields in your class are JSON serializable and which are inner classes, you could iterate over the values in your class's dictionary, check if they are JSON serializable, and convert them to dictionaries (value.__dict__) as necessary.