def METHOD_NAME(self, obj):
    if hasattr(obj, '_asdict'):  # detect namedtuple
        odct = obj._asdict()
        return dict(
            _namedtuple_name=type(obj).__name__,
            _namedtuple_fields=list(odct.keys()),
            _namedtuple_values=list(self.METHOD_NAME(o) for o in odct.values()),
        )
    elif isinstance(obj, set):
        return dict(_set_object=list(self.METHOD_NAME(o) for o in obj))
    elif isinstance(obj, dict):
        return {self.encode_key(k): self.METHOD_NAME(v) for k, v in obj.items()}
    elif isinstance(obj, tuple):
        return dict(_tuple_object=list(self.METHOD_NAME(o) for o in obj))
    else:
        return obj