r"""
    Converts a python object to a JSON string using the utool convention

    Args:
        val (object):

    Returns:
        str: json_str

    References:
        http://stackoverflow.com/questions/11561932/why-does-json-dumpslistnp

    CommandLine:
        python -m utool.util_cache --test-to_json
        python3 -m utool.util_cache --test-to_json

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_cache import *  # NOQA
        >>> import utool as ut
        >>> import numpy as np
        >>> import uuid
        >>> val = [
        >>>     '{"foo": "not a dict"}',
        >>>     1.3,
        >>>     [1],
        >>>     # {1: 1, 2: 2, 3: 3}, cant use integer keys
        >>>     {1, 2, 3},
        >>>     slice(1, None, 1),
        >>>     b'an ascii string',
        >>>     np.array([1, 2, 3]),
        >>>     ut.get_zero_uuid(),
        >>>     ut.LazyDict(x='fo'),
        >>>     ut.LazyDict,
        >>>     {'x': {'a', 'b', 'cde'}, 'y': [1]}
        >>> ]
        >>> #val = ut.LazyDict(x='fo')
        >>> allow_pickle = True
        >>> if not allow_pickle:
        >>>     val = val[:-2]
        >>> json_str = ut.to_json(val, allow_pickle=allow_pickle)
        >>> result = ut.repr3(json_str)
        >>> reload_val = ut.from_json(json_str, allow_pickle=allow_pickle)
        >>> # Make sure pickle doesnt happen by default
        >>> try:
        >>>     json_str = ut.to_json(val)
        >>>     assert False or not allow_pickle, 'expected a type error'
        >>> except TypeError:
        >>>     print('Correctly got type error')
        >>> try:
        >>>     json_str = ut.from_json(val)
        >>>     assert False, 'expected a type error'
        >>> except TypeError:
        >>>     print('Correctly got type error')
        >>> print(result)
        >>> print('original = ' + ut.repr3(val, nl=1))
        >>> print('reconstructed = ' + ut.repr3(reload_val, nl=1))
        >>> assert reload_val[6] == val[6].tolist()
        >>> assert reload_val[6] is not val[6]

def to_json(val, allow_pickle=False, pretty=False):
    r"""
    Converts a python object to a JSON string using the utool convention

    Args:
        val (object):

    Returns:
        str: json_str

    References:
        http://stackoverflow.com/questions/11561932/why-does-json-dumpslistnp

    CommandLine:
        python -m utool.util_cache --test-to_json
        python3 -m utool.util_cache --test-to_json

    Example:
        >>> # ENABLE_DOCTEST
        >>> from utool.util_cache import *  # NOQA
        >>> import utool as ut
        >>> import numpy as np
        >>> import uuid
        >>> val = [
        >>>     '{"foo": "not a dict"}',
        >>>     1.3,
        >>>     [1],
        >>>     # {1: 1, 2: 2, 3: 3}, cant use integer keys
        >>>     {1, 2, 3},
        >>>     slice(1, None, 1),
        >>>     b'an ascii string',
        >>>     np.array([1, 2, 3]),
        >>>     ut.get_zero_uuid(),
        >>>     ut.LazyDict(x='fo'),
        >>>     ut.LazyDict,
        >>>     {'x': {'a', 'b', 'cde'}, 'y': [1]}
        >>> ]
        >>> #val = ut.LazyDict(x='fo')
        >>> allow_pickle = True
        >>> if not allow_pickle:
        >>>     val = val[:-2]
        >>> json_str = ut.to_json(val, allow_pickle=allow_pickle)
        >>> result = ut.repr3(json_str)
        >>> reload_val = ut.from_json(json_str, allow_pickle=allow_pickle)
        >>> # Make sure pickle doesnt happen by default
        >>> try:
        >>>     json_str = ut.to_json(val)
        >>>     assert False or not allow_pickle, 'expected a type error'
        >>> except TypeError:
        >>>     print('Correctly got type error')
        >>> try:
        >>>     json_str = ut.from_json(val)
        >>>     assert False, 'expected a type error'
        >>> except TypeError:
        >>>     print('Correctly got type error')
        >>> print(result)
        >>> print('original = ' + ut.repr3(val, nl=1))
        >>> print('reconstructed = ' + ut.repr3(reload_val, nl=1))
        >>> assert reload_val[6] == val[6].tolist()
        >>> assert reload_val[6] is not val[6]
    """
    UtoolJSONEncoder = make_utool_json_encoder(allow_pickle)
    json_kw = {}
    json_kw['cls'] = UtoolJSONEncoder
    if pretty:
        json_kw['indent'] = 4
        json_kw['separators'] = (',', ': ')
    json_str = json.dumps(val, **json_kw)
    return json_str