class DictExporter(object): def __init__(self, dictcls=dict, attriter=None, childiter=list, maxlevel=None): """ Tree to dictionary exporter. Every node is converted to a dictionary with all instance attributes as key-value pairs. Child nodes are exported to the children attribute. A list of dictionaries. Keyword Args: dictcls: class used as dictionary. :any:`dict` by default. attriter: attribute iterator for sorting and/or filtering. childiter: child iterator for sorting and/or filtering. maxlevel (int): Limit export to this number of levels. >>> from pprint import pprint # just for nice printing >>> from anytree import AnyNode >>> from anytree.exporter import DictExporter >>> root = AnyNode(a="root") >>> s0 = AnyNode(a="sub0", parent=root) >>> s0a = AnyNode(a="sub0A", b="foo", parent=s0) >>> s0b = AnyNode(a="sub0B", parent=s0) >>> s1 = AnyNode(a="sub1", parent=root) >>> exporter = DictExporter() >>> pprint(exporter.export(root)) # order within dictionary might vary! {'a': 'root', 'children': [{'a': 'sub0', 'children': [{'a': 'sub0A', 'b': 'foo'}, {'a': 'sub0B'}]}, {'a': 'sub1'}]} Pythons dictionary `dict` does not preserve order. :any:`collections.OrderedDict` does. In this case attributes can be ordered via `attriter`. >>> from collections import OrderedDict >>> exporter = DictExporter(dictcls=OrderedDict, attriter=sorted) >>> pprint(exporter.export(root)) OrderedDict([('a', 'root'), ('children', [OrderedDict([('a', 'sub0'), ('children', [OrderedDict([('a', 'sub0A'), ('b', 'foo')]), OrderedDict([('a', 'sub0B')])])]), OrderedDict([('a', 'sub1')])])]) The attribute iterator `attriter` may be used for filtering too. For example, just dump attributes named `a`: >>> exporter = DictExporter(attriter=lambda attrs: [(k, v) for k, v in attrs if k == "a"]) >>> pprint(exporter.export(root)) {'a': 'root', 'children': [{'a': 'sub0', 'children': [{'a': 'sub0A'}, {'a': 'sub0B'}]}, {'a': 'sub1'}]} The child iterator `childiter` can be used for sorting and filtering likewise: >>> exporter = DictExporter(childiter=lambda children: [child for child in children if "0" in child.a]) >>> pprint(exporter.export(root)) {'a': 'root', 'children': [{'a': 'sub0', 'children': [{'a': 'sub0A', 'b': 'foo'}, {'a': 'sub0B'}]}]} """ self.dictcls = dictcls self.attriter = attriter self.childiter = childiter self.maxlevel = maxlevel def export(self, node): """Export tree starting at `node`.""" attriter = self.attriter or (lambda attr_values: attr_values) return self.__export(node, self.dictcls, attriter, self.childiter) def __export(self, node, dictcls, attriter, childiter, level=1): attr_values = attriter(self._iter_attr_values(node)) data = dictcls(attr_values) maxlevel = self.maxlevel if maxlevel is None or level < maxlevel: children = [self.__export(child, dictcls, attriter, childiter, level=level + 1) for child in childiter(node.children)] if children: data['children'] = children return data def _iter_attr_values(self, node): for k, v in node.__dict__.items(): if k in ('_NodeMixin__children', '_NodeMixin__parent'): continue yield k, v