Skip to content

Instantly share code, notes, and snippets.

@wellic
Created September 26, 2019 13:25
Show Gist options
  • Save wellic/aad14be76369b8b02c96167b3a5c7448 to your computer and use it in GitHub Desktop.
Save wellic/aad14be76369b8b02c96167b3a5c7448 to your computer and use it in GitHub Desktop.
Nested dict <-> path (flatten dict)
import json
SEPARATOR = '/'
def encode_value(value):
return json.dumps(value, indent=2, sort_keys=True)
def decode_value(item_value):
if hasattr(item_value, 'decode'):
item_value = item_value.decode()
try:
result = json.loads(item_value)
except:
result = item_value
return result
def decode_key(path, item_key, separator):
return (item_key[len(path):] if item_key.startswith(path) else item_key).split(separator)
def dict_to_flatten_list(data, key='', separator=SEPARATOR, prefix=''):
def _process(data, key='', separator=SEPARATOR, prefix=''):
return {separator.join(filter(None, [key, prefix, k1 if prefix else k1])): v1 # NOSONAR
for k2, v2 in data.items()
for k1, v1 in _process(key='', data=v2, separator=separator, prefix=k2).items()
} if isinstance(data, dict) else {
separator.join(filter(None, [key, prefix])): encode_value(data)}
if key:
return _process(data=data, key=key, separator=separator)
return {'': encode_value(data)}
def flatten_list_to_dict(data, key='', separator=SEPARATOR):
def _insert(dct, lst):
for x in lst[:-2]:
dct[x] = dct = dct.get(x, {})
dct.update({lst[-2]: lst[-1]})
if not data:
return None
if isinstance(data, (list, set, tuple)):
lsts = list([*(decode_key(key, item['Key'], separator)), decode_value(item['Value'])] for item in data)
result = {}
for lst in lsts:
keys = list(filter(None, lst[:-1]))
if not keys:
return lst[-1]
_insert(result, [*keys, lst[-1]])
return result
if data and isinstance(data, dict):
if '' in data:
return decode_value(data[''])
else:
flatten_list = [{'Key': k, "Value": v} for k, v in data.items()]
return flatten_list_to_dict(flatten_list, key=key, separator=separator)
if isinstance(data, str):
return json.loads(data)
return data
def pop_param_from_dict(args, key, default_value=None):
return args.pop(key, default_value) if isinstance(args, dict) else default_value
def prepare_full_path_name(keys=None, separator=SEPARATOR):
try:
if isinstance(keys, (str, int, float,)):
path = keys.strip(separator)
elif isinstance(keys, (dict, set, list, tuple)):
path = separator.join(key.strip(separator) for key in filter(None, keys))
else:
raise Exception('Unallowed type')
return path.strip()
except:
return None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment