Skip to content

Instantly share code, notes, and snippets.

@efim-a-efim
Created June 22, 2018 13:18
Show Gist options
  • Save efim-a-efim/1515a0c8716fc493cd06c0c3a5e166cd to your computer and use it in GitHub Desktop.
Save efim-a-efim/1515a0c8716fc493cd06c0c3a5e166cd to your computer and use it in GitHub Desktop.
Python dict data Key-Value serializer and deserializer

Input structure:

{ 
  'data': { 'backup': 'oqwpnruvq3r89q24hgq0fgy183ogb76w25v94g16fg981qo3f',
            'mysql': { 'asd': [ 'staff1',
                                'staff2',
                                { 'arr': [ 'service',
                                           'host',
                                           { 'asd': 'fff'}],
                                  'name': 'nonsense',
                                  'skip': 'apples',
                                  'value': 'True'},
                                112.0,
                                'asdasdasd'],
                       'host': 'myhost.mydomain',
                       'paas': 'True',
                       'qwe': 123.5}},
  'sample1': 'asdasdasdasda',
  'sample2': ['qwerty', 'somestaff']
  }

Serialized data:

data--mysql--asd--2--name: nonsense
data--mysql--host: myhost.mydomain
data--mysql--asd--2--arr--0: service
data--mysql--asd--2--arr--1: host
sample2--0: qwerty
data--mysql--asd--3: 112
data--backup: oqwpnruvq3r89q24hgq0fgy183ogb76w25v94g16fg981qo3f
data--mysql--paas: True
sample1: asdasdasdasda
data--mysql--qwe: 123.5
sample2--1: somestaff
data--mysql--asd--2--arr--2--asd: fff
data--mysql--asd--2--value: True
data--mysql--asd--4: asdasdasd
data--mysql--asd--2--skip: apples
data--mysql--asd--1: staff2
data--mysql--asd--0: staff1

Deserialized data:

{ 'data': { 'backup': 'oqwpnruvq3r89q24hgq0fgy183ogb76w25v94g16fg981qo3f',
            'mysql': { 'asd': [ 'staff1',
                                'staff2',
                                { 'arr': [ 'service',
                                           'host',
                                           { 'asd': 'fff'}],
                                  'name': 'nonsense',
                                  'skip': 'apples',
                                  'value': 'True'},
                                112.0,
                                'asdasdasd'],
                       'host': 'myhost.mydomain',
                       'paas': 'True',
                       'qwe': 123.5}},
  'sample1': 'asdasdasdasda',
  'sample2': ['qwerty', 'somestaff']}
def flat_deserialize(structure, separator='--', replace_dashes=False):
def unflatten(keys, value, replace_dashes=False):
if len(keys) == 0:
return value
try:
# if key is convertable to integer - it's an array
k = int(keys[0])
l = [None]*(k+1)
l[k] = unflatten(keys[1:], value, replace_dashes)
return l
except ValueError:
pass
k = str(keys[0])
if (replace_dashes):
k = k.replace('-','_')
return {k: unflatten(keys[1:], value, replace_dashes)}
def merge_lists(l1, l2):
ret = [None]*max(len(l1), len(l2))
for i in range(max(len(l1), len(l2))):
if (len(l1) <= i or l1[i] is None) and len(l2) > i:
ret[i] = l2[i]
elif (len(l2) <= i or l2[i] is None) and len(l1) > i:
ret[i] = l1[i]
elif isinstance(l1[i], dict) and isinstance(l2[i], dict):
# merge dicts
ret[i] = merge(l1[i], l2[i])
elif isinstance(l1[i], list) and isinstance(l2[i], list):
ret[i] = merge_lists(l1[i], l2[i])
elif len(l2) > i:
ret[i] = l2[i]
else:
ret[i] = None
return ret
def merge(base, data):
ret = dict()
for k in set(base.keys()).union(data.keys()):
if k in base and k in data:
if isinstance(base[k], dict) and isinstance(data[k], dict):
# if both are dicts - merge them recursively
ret[k] = merge(base[k], data[k])
elif isinstance(base[k], list) and isinstance(data[k], list):
# Array indexes are in serialized keys, so we surely can identify needed list member
ret[k] = merge_lists(base[k], data[k])
else:
ret[k] = data[k]
elif k in base:
ret[k] = base[k]
elif k in data:
ret[k] = data[k]
return ret
ret = dict()
for item in structure:
# load value
v = structure[item]
try:
v = int(v)
except ValueError:
pass
try:
v = float(v)
except ValueError:
pass
data = unflatten(item.split(separator), v)
ret = merge(ret, data)
return ret
def flat_serialize(structure, separator='--'):
if isinstance(structure, dict):
ret = dict()
for item in structure:
# we have dict - go deeper. index = xxxx-yyy, xxxx-zzz, etc.
fl = flat_serialize(structure[item])
if isinstance(fl, dict):
# we have some sub-structure here
for i in fl:
ret[ item + separator + i ] = fl[i]
else:
# just scalar value
ret[item] = fl
return ret
elif isinstance(structure, list):
ret = dict()
# list - serialize elements as usual
for idx in range(len(structure)):
fl = flat_serialize(structure[idx])
if isinstance(fl, dict):
# we have some sub-structure here. index = xxxx-0-yyy, xxxx-1-yyy, ext.
for i in fl:
ret[ str(idx) + separator + i ] = fl[i]
else:
# scalar - index = xxxx-0, xxxx-1, etc.
ret[str(idx)] = fl
return ret
else:
# all other types are scalars - convert to strings
return str(structure)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment