def json_clean(obj):
    # types that are 'atomic' and ok in json as-is.  bool doesn't need to be
    # listed explicitly because bools pass as int instances
    atomic_ok = (str, int, float, type(None))
    
    # containers that we need to convert into lists
    container_to_list = (tuple, set, range, types.GeneratorType)
    
    if isinstance(obj, atomic_ok):
        return obj

    if isinstance(obj, container_to_list) or (
        hasattr(obj, '__iter__') and hasattr(obj, '__next__')):
        obj = list(obj)
        
    if isinstance(obj, list):
        return [json_clean(x) for x in obj]

    if isinstance(obj, dict):
        # First, validate that the dict won't lose data in conversion due to
        # key collisions after stringification.  This can happen with keys like
        # True and 'true' or 1 and '1', which collide in JSON.
        nkeys = len(obj)
        nkeys_collapsed = len(set(map(str, obj)))
        if nkeys != nkeys_collapsed:
            raise ValueError('dict can not be safely converted to JSON: '
                             'key collision would lead to dropped values')
        # If all OK, proceed by making the new dict that will be json-safe
        out = {}
        for k,v in obj.items():
            out[str(k)] = json_clean(v)
        return out

    # If we get here, we don't know how to handle the object, so we just get
    # its repr and return that.  This will catch lambdas, open sockets, class
    # objects, and any other complicated contraption that json can't encode
    return repr(obj)
Clean an object to ensure it's safe to encode in JSON.
dataset/ETHPy150Open ipython/ipython-py3k/IPython/utils/jsonutil.py/json_clean