Update lookup_api.py
Created by: Salfiii
makes it possible to provide a list of values to nested_update which is handy if a node exists multiple times in the document but should not get overwritten with the same value. Works best in combination if you use nested_lookup() before, modify the results you get and pass those to nested update. Example:
import copy
from six import iteritems
from nested_lookup import nested_lookup
doc = {
"modelversion": "1.1.0",
"vorgangsID": "1",
"versorgungsvorschlagDatum": 1510558834978,
"eingangsdatum": 1510558834978,
"plz": 82269,
"vertragsteile": [
{
"typ": "1",
"beitragsDaten": {
"endalter": 85,
"brutto": 58.76,
"netto": 58.76,
"zahlungsrhythmus": "MONATLICH",
"plz": 86899
},
"beginn": 1512082800000,
"lebenslang": "True",
"ueberschussverwendung": {
"ueberschussverwendung": "2",
"indexoption": "3"
},
"deckung": [
{
"typ": "2",
"art": "1",
"leistung": {
"value": 7500242424.0,
"einheit": "2"
},
"leistungsRhythmus": "1"
}
],
"zuschlagNachlass": []
},
{
"typ": "1",
"beitragsDaten": {
"endalter": 85,
"brutto": 0.6,
"netto": 0.6,
"zahlungsrhythmus": "1"
},
"zuschlagNachlass": []
}
]
}
def nested_update(document, key, value, in_place=False):
"""
Method to update a key->value pair in a nested document
Args:
document: Might be List of Dicts (or) Dict of Lists (or)
Dict of List of Dicts etc...
key: Key to update the value
Return:
Returns a document that has updated key, value pair.
"""
# check if a list or scalar value is provided and create a list from the scalar value
# check the length of the list and provide it to _nested_update
if type(value) == list:
val_len = len(value)
else:
value = [value]
val_len = len(value)
if not in_place:
document = copy.deepcopy(document)
return _nested_update(document=document, key=key, value=value, val_len = val_len)
def _nested_update(document, key, value, val_len, run = 0):
"""
Method to update a key->value pair in a nested document
Args:
document: Might be List of Dicts (or) Dict of Lists (or)
Dict of List of Dicts etc...
key (str): Key to update the value
value (list): value(s) which should be used for replacement purpouse
val_len (int): lenght of the value element
run (int): holds the number of findings for the given key.
Every time the key is found, run = run + 1. If the list value[run] exists,
the corresponding element is used for replacement purpouse.
Defaults to 0.
Return:
Returns a document that has updated key, value pair.
"""
if isinstance(document, list):
for list_items in document:
_nested_update(document=list_items, key=key, value=value, val_len = val_len, run = run)
elif isinstance(document, dict):
if document.get(key):
# check if a value with the coresponding index exists and use it otherwise recycle the intially given value
val = value[run] if run < val_len else value[0]
document[key] = val
run = run + 1
for dict_key, dict_value in iteritems(document):
_nested_update(document=dict_value, key=key, value=value, val_len = val_len, run = run)
return document
# get all instances of the given element
findings = nested_lookup("plz", doc, False,True)
# alter those instances
updated_findins = list()
for key, val in findings.items():
for elem in val:
updated_findins.append(elem + 300)
# update those instances with the altered results
print("**************************** LIST ARG ****************************")
print(nested_update(doc,"plz",updated_findins))
print("**************************** SCALAR ARG ****************************")
# now a regular use with just one argument to test the backwards portability
print(nested_update(doc,"plz", "12345"))