def todict_using_struct(self, dict_struct=None, dict_post_processors=None):
        """
            dict_struct:
            {
                'attrs': ['id', 'created_at'],
                'rels': {
                    'merchandise': {
                        'attrs': ['id', 'label']
                    }
                }
            }
        """
        # It is important to assign the passed kwarg to a differently named variable.
        # A dict is passed by reference and using the same kwarg here results in it
        # getting mutated - causing unforeseen side effects
        dict_struct_to_use = (
            self._dict_struct_ if dict_struct is None
            else dict_struct)
        if dict_struct_to_use is None and self._autogenerate_dict_struct_if_none_:
            dict_struct_to_use = self.autogenerated_dict_structure()
        elif dict_struct.get("attrs") is None:
            dict_struct_to_use = {}
            dict_struct_to_use["attrs"] = self.autogenerated_dict_structure()["attrs"]
            if "rels" in dict_struct:
                dict_struct_to_use["rels"] = dict_struct.get("rels")
        result = self.serialize_attrs(*dict_struct_to_use.get('attrs', []))
        for rel, rel_dict_struct in dict_struct_to_use.get('rels', {}).items():
            rel_obj = getattr(self, rel) if hasattr(self, rel) else None
            if rel_obj is not None:
                if is_list_like(rel_obj):
                    result[rel] = [i.todict_using_struct(dict_struct=rel_dict_struct)
                                   if hasattr(i, 'todict_using_struct') else i
                                   for i in rel_obj]
                elif is_dict_like(rel_obj):
                    result[rel] = {k: v.todict_using_struct(dict_struct=rel_dict_struct)
                                   if hasattr(v, 'todict_using_struct') else v
                                   for k, v in rel_obj.iteritems()}
                else:
                    result[rel] = rel_obj.todict_using_struct(
                        dict_struct=rel_dict_struct) if hasattr(
                        rel_obj, 'todict_using_struct') else rel_obj
            else:
                result[rel] = None
        if isinstance(dict_post_processors, list):
            for dict_post_processor in dict_post_processors:
                if callable(dict_post_processor):
                    result = dict_post_processor(result, self)
        return result