Serializing a user-defined class in Python
Question: got a question regarding serializing classes that I've defined. I have some
classes like

    
    
    class Foo:
         def __init__(self, x, y):
              self.x = x, self.y = y
    
         def toDict(self):
              return dict(Foo = dict(x = self.x, y = self.y))
    

then a class that can contain multiple Foos, such as:

    
    
    class Bar:
         def __init__(self):
              self.foos = [Foo(a, b), Foo(1, 2)]
    

While that's a gross oversimplification of the real structure (it gets much,
much more nested than that), that's a pretty decent overview. The actual data
for this is coming from a pseudo-XML file without any actual structure, so I
wrote a parser according to the spec given to me, so I now have all the data
in a series of classes I've defined, with actual structure.

What I'm wanting to do is take this data I have and spit it out into JSON, but
I really don't see a good way (I'm new to Python, this is my first real
project with it).

I've defined a method in Foo, toDict(), that creates a dictionary out of the
information, but that obviously isn't going to work out like I hope when I try
to serialize Bar, with the multiple Foos.

Does anyone have a great way of doing this? This has been a pretty much non-
stop learning/codefest the past few days and I'm out of ideas for this, which
is the last part of the project. I know about the JSON module for Python, but
that doesn't help me with this particular problem of getting my data into a
dictionary (or something similar) that I can pass to json.dump().

Let me know if I can clarify in any way.

Thanks, T.J.


Answer: Several comments. First:

  * [`xml.dom.minidom`](http://docs.python.org/library/xml.dom.minidom.html) is a built-in Python DOM implementation. Obviously if the file isn't actually XML you won't be able to use it's builtin parsing functions, but it looks like you're building a tree-like structure out of the file anyway, in which case you might as well use a `minidom`.

OK, henceforth I'll assume that you have a good reason for writing your own
tree-style structure instead of using the builtins.

  * Are you sure the nodes should be classes? That seems like an awful lot of structure when all you really seem to need is a bunch of nested `dict`s:
    
        root = {
        "foo1": { "bar1": "spam", "bar2": "ham"},
        "foo2": { "baz1": "spam", "baz2": "ham"},
    }
    

You get the idea.

OK, maybe you're sure that you need the individual nodes to be classes. In
that case, they should all inherit from some `BaseNode` class, right? After
all, they are fundamentally similar things.

  * In that case, define a `BaseNode.serialise` method which effectively prints some information about itself and then calls `serialise` on all of its children. This is a recursive problem; you might as well use a recursive solution unless your tree is really really _really_ nested.

The `json` library allows you to subclass the `JSONEncoder` to do this.

    
        >>> import json
    >>> class ComplexEncoder(json.JSONEncoder):
    ...     def default(self, obj):
    ...         if isinstance(obj, complex):
    ...             return [obj.real, obj.imag]
    ...         return json.JSONEncoder.default(self, obj)
    ...
    >>> dumps(2 + 1j, cls=ComplexEncoder)
    '[2.0, 1.0]'
    >>> ComplexEncoder().encode(2 + 1j)
    '[2.0, 1.0]'
    >>> list(ComplexEncoder().iterencode(2 + 1j))
    ['[', '2.0', ', ', '1.0', ']']
    

