在使用常见的第三方库(deepdiff、json_tools、jsonpatch)获取两个json对象的差异后,如何根据差异,对json对象进行修改。如何从对比结果中获取数据的key是问题的关键。
拿deepdiff
举例:
from deepdiff import DeepDiff
a = {"name": "yanan", "pro": {"sh": "shandong", "city": ["zibo", "weifang"]}}
b = {"name": "Yanan", "pro": {"sh": "shandong", "town": ["taian", "weifang"]}}
result = DeepDiff(a, b)
print(result)
{'dictionary_item_added': [root['pro']['town']], 'dictionary_item_removed': [root['pro']['city']], 'values_changed': {"root['name']": {'new_value': 'Yanan', 'old_value': 'yanan'}}}
- 增加了一个item对象:
b['pro']['town']
- 移除了一个item对象:
a['pro']['city']
- 数据发生改变的有:
a['name']
变为b['name']
在deepdiff
库中,可以
- 使用
_path_to_elements
方法实现将root['name']
转换为(('name', 'GET'),)
:deepdiff.path._path_to_elements("root['name']", root_element=None)
- 然后使
_get_nested_obj
用获取原对象中对应的数据。deepdiff.path._get_nested_obj(b,(('name', 'GET'),))
在我的使用场景中,只关心对象的类型、数据是否发生改变,其他item对象的增加、删除并不关心。所以最终的实现的代码如下,大家可以根据自己的具体应用场景进行修改:
from deepdiff import DeepDiff
from deepdiff.path import _path_to_elements, _get_nested_obj
def update_json(new_json, old_json=None):
# 更新 json 文件
if not old_json:
return new_json
diff_obj = DeepDiff(old_json, new_json, verbose_level=2)
if diff_obj.get('type_changes'):
for _path, item in diff_obj['type_changes'].items():
if (isinstance(item['new_value'], list) or isinstance(item['new_value'], dict) \
or isinstance(item['new_value'], str)) and len(item['new_value']) == 0:
continue
cur_node = _path_to_elements(_path, root_element=None)
parent_node = _get_nested_obj(old_json, cur_node[:-1])
parent_node[cur_node[-1][0]] = item['new_value']
if diff_obj.get('values_changed'):
for _path, item in diff_obj['values_changed'].items():
cur_node = _path_to_elements(_path, root_element=None)
parent_node = _get_nested_obj(old_json, cur_node[:-1])
parent_node[cur_node[-1][0]] = item['new_value']
return old_json