如何将导出为JSON的Firefox书签合并为树形结构
将带路径的书签字典还原为Firefox树形结构
解决方案代码
def restore_bookmark_tree(path_dict): # 处理原get_bm_path返回的格式:路径对应[type_str, node_data] # 先提取所有节点数据,建立id到节点的映射 node_map = {} for item in path_dict.values(): # 兼容两种格式:直接node_data 或 [type_str, node_data] if isinstance(item, list): _, node_data = item else: node_data = item node_map[node_data['id']] = node_data.copy() # 为所有节点初始化children列表(文件夹后续会填充,书签节点最后会清理) for node in node_map.values(): node.setdefault('children', []) # 遍历每个路径,建立父子节点关系 root = None for path, item in path_dict.items(): # 拆分路径,过滤空字符串(路径以/结尾) parts = [p for p in path.split('/') if p] if not parts: continue # 获取当前节点 if isinstance(item, list): _, node_data = item else: node_data = item current_node = node_map[node_data['id']] # 根节点处理 if len(parts) == 1: root = current_node continue # 找到父节点并添加当前节点到其子列表 parent_id = parts[-2] parent_node = node_map[parent_id] if current_node not in parent_node['children']: parent_node['children'].append(current_node) # 递归清理无子女的children字段,符合Firefox原生格式 def clean_empty_children(node): if 'children' in node and not node['children']: del node['children'] if 'children' in node: for child in node['children']: clean_empty_children(child) if root: clean_empty_children(root) return root
测试示例
输入(兼容原代码返回格式和简化格式):
# 原代码get_bm_path返回的格式示例 merged_dict = { 'main_folder/': ['folder_main_folder', {'id': 'main_folder', 'ad': 'what'}], 'main_folder/subfolder1/': ['folder_subfolder1', {'id': 'subfolder1', 'ad': 'what'}], 'main_folder/subfolder1/9GEAbdFPVBqv/': ['uri_9GEAbdFPVBqv', {'id': '9GEAbdFPVBqv', 'ad': 'what1'}], 'main_folder/subfolder1/eaXY8H5Y1cJ_/': ['folder_eaXY8H5Y1cJ_', {'id': 'eaXY8H5Y1cJ_', 'ad': 'what2'}], 'main_folder/subfolder1/eaXY8H5Y1cJ_/9p2UFp7-qcEt/': ['uri_9p2UFp7-qcEt', {'id': '9p2UFp7-qcEt', 'ad': 'what3'}], 'main_folder/subfolder1/fijaCypbmbU1/': ['uri_fijaCypbmbU1', {'id': 'fijaCypbmbU1', 'ad': 'what4'}], 'main_folder/subfolder2/': ['folder_subfolder2', {'id': 'subfolder2', 'ad': 'what7'}] }
执行函数:
result = restore_bookmark_tree(merged_dict) print(result)
输出:
{'id': 'main_folder', 'ad': 'what', 'children': [ {'id': 'subfolder1', 'ad': 'what', 'children': [ {'id': '9GEAbdFPVBqv', 'ad': 'what1'}, {'id': 'eaXY8H5Y1cJ_', 'ad': 'what2', 'children': [{'id': '9p2UFp7-qcEt', 'ad': 'what3'}]}, {'id': 'fijaCypbmbU1', 'ad': 'what4'} ]}, {'id': 'subfolder2', 'ad': 'what7'} ]}
关键逻辑说明
- 节点映射表:用
node_map存储每个节点id对应的对象,避免递归查找,大幅提升构建效率。 - 格式兼容:同时支持原代码返回的
[类型标记, 节点数据]格式和简化的直接节点数据格式。 - 父子关系构建:通过拆分路径层级,快速定位当前节点的父节点,将其添加到父节点的子列表中。
- 格式清理:递归移除无子女节点的
children字段,完全匹配Firefox书签的原生JSON结构。
内容的提问来源于stack exchange,提问作者K Y
相关产品推荐
相关产品推荐

