You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将导出为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 17:07:50