:py:mod:`kwcoco.util.util_json` =============================== .. py:module:: kwcoco.util.util_json Module Contents --------------- Functions ~~~~~~~~~ .. autoapisummary:: kwcoco.util.util_json.ensure_json_serializable kwcoco.util.util_json.find_json_unserializable kwcoco.util.util_json.indexable_allclose Attributes ~~~~~~~~~~ .. autoapisummary:: kwcoco.util.util_json.IndexableWalker .. py:data:: IndexableWalker .. py:function:: ensure_json_serializable(dict_, normalize_containers=False, verbose=0) Attempt to convert common types (e.g. numpy) into something json complient Convert numpy and tuples into lists :Parameters: **normalize_containers** (*bool, default=False*) -- if True, normalizes dict containers to be standard python structures. .. rubric:: Example >>> data = ub.ddict(lambda: int) >>> data['foo'] = ub.ddict(lambda: int) >>> data['bar'] = np.array([1, 2, 3]) >>> data['foo']['a'] = 1 >>> data['foo']['b'] = (1, np.array([1, 2, 3]), {3: np.int32(3), 4: np.float16(1.0)}) >>> dict_ = data >>> print(ub.repr2(data, nl=-1)) >>> assert list(find_json_unserializable(data)) >>> result = ensure_json_serializable(data, normalize_containers=True) >>> print(ub.repr2(result, nl=-1)) >>> assert not list(find_json_unserializable(result)) >>> assert type(result) is dict .. py:function:: find_json_unserializable(data, quickcheck=False) Recurse through json datastructure and find any component that causes a serialization error. Record the location of these errors in the datastructure as we recurse through the call tree. :Parameters: * **data** (*object*) -- data that should be json serializable * **quickcheck** (*bool*) -- if True, check the entire datastructure assuming its ok before doing the python-based recursive logic. :returns: list of "bad part" dictionaries containing items 'value' - the value that caused the serialization error 'loc' - which contains a list of key/indexes that can be used to lookup the location of the unserializable value. If the "loc" is a list, then it indicates a rare case where a key in a dictionary is causing the serialization error. :rtype: List[Dict] .. rubric:: Example >>> from kwcoco.util.util_json import * # NOQA >>> part = ub.ddict(lambda: int) >>> part['foo'] = ub.ddict(lambda: int) >>> part['bar'] = np.array([1, 2, 3]) >>> part['foo']['a'] = 1 >>> # Create a dictionary with two unserializable parts >>> data = [1, 2, {'nest1': [2, part]}, {frozenset({'badkey'}): 3, 2: 4}] >>> parts = list(find_json_unserializable(data)) >>> print('parts = {}'.format(ub.repr2(parts, nl=1))) >>> # Check expected structure of bad parts >>> assert len(parts) == 2 >>> part = parts[1] >>> assert list(part['loc']) == [2, 'nest1', 1, 'bar'] >>> # We can use the "loc" to find the bad value >>> for part in parts: >>> # "loc" is a list of directions containing which keys/indexes >>> # to traverse at each descent into the data structure. >>> directions = part['loc'] >>> curr = data >>> special_flag = False >>> for key in directions: >>> if isinstance(key, list): >>> # special case for bad keys >>> special_flag = True >>> break >>> else: >>> # normal case for bad values >>> curr = curr[key] >>> if special_flag: >>> assert part['data'] in curr.keys() >>> assert part['data'] is key[1] >>> else: >>> assert part['data'] is curr .. py:function:: indexable_allclose(dct1, dct2, return_info=False) Walks through two nested data structures and ensures that everything is roughly the same. :Parameters: * **dct1** -- a nested indexable item * **dct2** -- a nested indexable item .. rubric:: Example >>> from kwcoco.util.util_json import indexable_allclose >>> dct1 = { >>> 'foo': [1.222222, 1.333], >>> 'bar': 1, >>> 'baz': [], >>> } >>> dct2 = { >>> 'foo': [1.22222, 1.333], >>> 'bar': 1, >>> 'baz': [], >>> } >>> assert indexable_allclose(dct1, dct2)