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

为何JSON文件无法根据depth参数实现层级嵌套缩进?

问题分析与解决方案

问题根源

你当前的代码存在两个核心问题:

  1. 循环覆盖文件:每次循环都打开output.json并以写模式覆盖,最终文件只会保留最后一次循环的缩进设置,前面的操作完全无效。
  2. json.dump的indent是全局参数:这个参数控制的是整个JSON结构的基础缩进步长,所有层级都会基于这个值递进(比如indent=4时,第一层4空格,第二层8空格),无法单独为某个子对象设置自定义的缩进深度。

解决方案

标准库的json模块不支持为单个元素设置独立缩进,需要手动实现自定义格式化逻辑。下面提供两种可行方案:

方案1:自定义递归序列化函数

通过递归遍历数据结构,针对submodules中的每个元素使用对应depth值设置缩进:

import os

def custom_json_serialize(obj, indent_step=4, depth_map=None, current_list=None):
    indent = ' ' * indent_step
    if isinstance(obj, dict):
        items = []
        for key, value in obj.items():
            key_str = f'"{key}"'
            # 递归处理值,层级+1
            value_str = custom_json_serialize(value, indent_step, depth_map, current_list)
            items.append(f'{indent}{key_str}: {value_str}')
        return '{\n' + ',\n'.join(items) + f'\n{indent[:-indent_step]}}}'
    elif isinstance(obj, list):
        elements = []
        # 标记当前处理的列表是否是submodules
        is_submodules = current_list == "submodules"
        for idx, elem in enumerate(obj):
            # 如果是submodules列表,使用对应的depth值作为起始缩进层级
            start_depth = depth_map[idx] if is_submodules else 1
            elem_str = custom_json_serialize(elem, indent_step, depth_map)
            # 生成对应层级的缩进
            elem_indent = ' ' * (start_depth * indent_step)
            elements.append(f'{elem_indent}{elem_str}')
        # 列表的外层缩进用顶层层级
        outer_indent = indent[:-indent_step] if not is_submodules else ''
        return '[\n' + ',\n'.join(elements) + f'\n{outer_indent}]'
    elif isinstance(obj, str):
        return f'"{obj}"'
    else:
        return str(obj)

def main(directory_path):
    submodules, depth = parse_directory(directory_path)
    output = {
        "name": os.path.basename(directory_path),
        "repository": os.path.dirname(os.path.realpath(directory_path)),
        "submodules": submodules
    }
    
    # 调用自定义序列化函数,传入depth作为submodules的缩进层级映射
    json_str = custom_json_serialize(output, depth_map=depth, current_list="submodules")
    # 手动添加顶层对象的缩进
    json_str = json_str.replace('{', '{\n    ', 1)
    with open("output.json", "w") as output_file:
        output_file.write(json_str)

方案2:先序列化再替换内容

先将整个对象序列化为无缩进的JSON字符串,再针对每个submodule替换为带对应缩进的版本:

import json
import os

def main(directory_path):
    submodules, depth = parse_directory(directory_path)
    output = {
        "name": os.path.basename(directory_path),
        "repository": os.path.dirname(os.path.realpath(directory_path)),
        "submodules": submodules
    }
    
    # 先序列化为无缩进的字符串
    raw_json = json.dumps(output, separators=(',', ':'))
    
    # 逐个替换submodule为带对应缩进的格式
    for submod, d in zip(submodules, depth):
        # 生成带指定缩进的submodule字符串
        indented_submod = json.dumps(submod, indent=d*4)
        # 生成原始无缩进的submodule字符串用于匹配替换
        raw_submod = json.dumps(submod)
        # 替换(注意:如果存在重复的submodule会替换所有匹配项,需确保submodule唯一)
        raw_json = raw_json.replace(raw_submod, indented_submod)
    
    # 最后给顶层对象添加基础缩进
    formatted_json = raw_json.replace('{"name"', '{\n    "name"').replace('"submodules":', '\n    "submodules":')
    with open("output.json", "w") as output_file:
        output_file.write(formatted_json)

注意事项

  • 方案2中如果submodules存在完全相同的元素,会替换所有匹配项,适合元素唯一的场景;
  • 方案1的自定义序列化逻辑更灵活,可根据实际数据结构调整递归处理规则。

内容的提问来源于stack exchange,提问作者kitchat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 05:12:51