code: def todict(obj, post_processor=None):  # pylint: disable=too-many-return-statements
      
      if isinstance(obj, dict):
          result = {k: todict(v, post_processor) for (k, v) in obj.items()}
          return post_processor(obj, result) if post_processor else result
      if isinstance(obj, list):
          return [todict(a, post_processor) for a in obj]
      if isinstance(obj, Enum):
          return obj.value
      if isinstance(obj, (date, time, datetime)):
          return obj.isoformat()
      if isinstance(obj, timedelta):
          return str(obj)
      if hasattr(obj, '_asdict'):
          return todict(obj._asdict(), post_processor)
      if hasattr(obj, '__dict__'):
          result = {to_camel_case(k): todict(v, post_processor)
                    for k, v in obj.__dict__.items()
                    if not callable(v) and not k.startswith('_')}
          return post_processor(obj, result) if post_processor else result
      return obj
docs: Convert an object to a dictionary. Use 'post_processor(original_obj, dictionary)' to update the
      dictionary in the process