kwcoco.util.util_json module¶
Deprecated: use kwutil.Json instead
- kwcoco.util.util_json.ensure_json_serializable(dict_, normalize_containers=False, verbose=0)[source]¶
Attempt to convert common types (e.g. numpy) into something json compliant
Convert numpy and tuples into lists
- Parameters:
normalize_containers (bool) – if True, normalizes dict containers to be standard python structures. Defaults to False.
Note
This function is now in kwutil. Might be best to use that variant. See
kwutil.util_json.ensure_json_serializable().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.urepr(data, nl=-1)) >>> assert list(find_json_unserializable(data)) >>> result = ensure_json_serializable(data, normalize_containers=True) >>> print(ub.urepr(result, nl=-1)) >>> assert not list(find_json_unserializable(result)) >>> assert type(result) is dict
- kwcoco.util.util_json.find_json_unserializable(data, quickcheck=False)[source]¶
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.
Note
This function is now in kwutil. Might be best to use that variant. See
kwutil.util_json.find_json_unserializable().- 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.
- Return type:
List[Dict]
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.urepr(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
Example
>>> # xdoctest: +SKIP("TODO: circular ref detect algo is wrong, fix it") >>> from kwcoco.util.util_json import * # NOQA >>> import pytest >>> # Test circular reference >>> data = [[], {'a': []}] >>> data[1]['a'].append(data) >>> with pytest.raises(ValueError, match="Circular reference detected at.*1, 'a', 1*"): ... parts = list(find_json_unserializable(data)) >>> # Should be ok here >>> shared_data = {'shared': 1} >>> data = [[shared_data], shared_data] >>> parts = list(find_json_unserializable(data))
- kwcoco.util.util_json.indexable_allclose(dct1, dct2, return_info=False)[source]¶
Walks through two nested data structures and ensures that everything is roughly the same.
Note
DEPRECATED. Use
ubelt.IndexableWalker.allclose()instead.- Parameters:
dct1 – a nested indexable item
dct2 – a nested indexable item
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)
- class kwcoco.util.util_json.Difference(path: Tuple, value1: Any, value2: Any)[source]¶
Bases:
NamedTupleA result class of indexable_diff that organizes what the difference between the indexables is.
Create new instance of Difference(path, value1, value2)
- _asdict()¶
Return a new dict which maps field names to their values.
- _field_defaults = {}¶
- _fields = ('path', 'value1', 'value2')¶
- classmethod _make(iterable)¶
Make a new Difference object from a sequence or iterable
- _replace(**kwds)¶
Return a new Difference object replacing specified fields with new values
- kwcoco.util.util_json.indexable_diff(dct1, dct2, rtol=1e-05, atol=1e-08, equal_nan=False)[source]¶
Walks through two nested data structures finds differences in the structures.
- Parameters:
dct1 – a nested indexable item
dct2 – a nested indexable item
Note
DEPRECATED. Use
ubelt.IndexableWalker.diff()instead.- Returns:
- information about the diff with
”similarity”: a score between 0 and 1 “num_differences” being the number of paths not common plus the
number of common paths with differing values.
”unique1”: being the paths that were unique to dct1 “unique2”: being the paths that were unique to dct2 “faillist”: a list 3-tuples of common path and differing values “approximations”:
is the number of approximately equal items (i.e. floats) there were
- Return type:
Example
>>> from kwcoco.util.util_json import indexable_diff >>> dct1 = { >>> 'foo': [1.222222, 1.333], >>> 'bar': 1, >>> 'baz': [], >>> 'top': [1, 2, 3], >>> 'L0': {'L1': {'L2': {'K1': 'V1', 'K2': 'V2', 'D1': 1, 'D2': 2}}}, >>> } >>> dct2 = { >>> 'foo': [1.22222, 1.333], >>> 'bar': 1, >>> 'baz': [], >>> 'buz': {1: 2}, >>> 'top': [1, 1, 2], >>> 'L0': {'L1': {'L2': {'K1': 'V1', 'K2': 'V2', 'D1': 10, 'D2': 20}}}, >>> } >>> info = indexable_diff(dct1, dct2) >>> print(f'info = {ub.urepr(info, nl=2)}')