docs: 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