【Python】查找并替换指定文件夹内所有JSON 文件的类别名称-完整代码

一、类别名称修改前后对比

1、类别名称修改前:pedestrians

2、类别名称修改后:person

二、代码介绍

1、功能介绍

  • 多类别批量替换:通过配置映射字典,可以一次性替换多个不同的类别名称
  • 灵活的匹配模式:支持区分大小写或不区分大小写的类别名称匹配
  • 安全的文件处理:不会覆盖原始文件,所有修改都保存在新目录中
  • 详细的处理反馈:显示进度条和处理统计信息,支持详细模式查看具体修改
  • 智能递归处理:自动处理嵌套结构的 JSON 数据,确保不漏过任何类别名称

2、使用方法

  • 打开代码文件
  • 修改变量:
    • INPUT_DIR:输入 JSON 文件目录
    • OUTPUT_DIR:输出 JSON 文件目录
    • 修改CLASS_MAPPING
      • 需要替换的原类别名称
      • 替换后的新类别名称
  • 直接运行脚本

3、完整代码 

# 导入操作系统相关功能模块,用于文件和目录操作
import os
# 导入JSON处理模块,用于解析和生成JSON文件
import json
# 导入命令行参数解析模块(当前版本未使用,但保留以支持未来扩展)
import argparse
# 导入进度条显示模块,用于直观展示处理进度
from tqdm import tqdm

# === 在这里修改参数 ===
# 定义输入JSON文件所在的目录路径
INPUT_DIR = r"D:\AAAAdata\json123"
# 定义处理后JSON文件保存的目录路径
OUTPUT_DIR = r"D:\AAAAdata\newjson123"

# 定义需要替换的类别映射字典,键为原类别名称,值为新类别名称
CLASS_MAPPING = {
    "pedestrians": "person",
    #"car": "automobile",
    #"dog": "canine",
    #"cat": "feline"
}

# 是否区分大小写进行类别名称匹配(True: 区分,False: 不区分)
CASE_SENSITIVE = True
# 是否显示详细的处理信息(True: 显示,False: 只显示摘要)
VERBOSE = True


# =====================

def find_and_replace(obj, class_mapping, case_sensitive=True):
    """
    递归查找并替换JSON对象中的多个类别名称

    参数:
    obj (dict/list): 要处理的JSON对象(字典或列表)
    class_mapping (dict): 类别映射字典,格式为 {"原类别名称": "新类别名称"}
    case_sensitive (bool): 是否区分大小写

    返回:
    bool: 是否进行了替换
    """
    # 初始化修改标志为False,表示尚未进行任何修改
    modified = False

    # 如果当前处理的对象是字典类型
    if isinstance(obj, dict):
        # 遍历字典中的每个键值对
        for key, value in obj.items():
            # 检查当前值是否为字符串类型
            if isinstance(value, str):
                # 根据是否区分大小写选择不同的匹配逻辑
                if case_sensitive:
                    # 如果当前字符串值存在于类别映射字典的键中
                    if value in class_mapping:
                        # 获取对应的新类别名称
                        new_value = class_mapping[value]
                        # 替换字典中的值为新类别名称
                        obj[key] = new_value
                        # 标记已进行修改
                        modified = True
                        # 如果启用详细模式,打印替换信息
                        if VERBOSE:
                            print(f"替换: {key} = {new_value}")
                else:
                    # 不区分大小写时,将当前字符串转为小写
                    lower_value = value.lower()
                    # 遍历类别映射字典中的每个原类别名称
                    for old_class, new_class in class_mapping.items():
                        # 如果小写后的当前字符串与原类别名称匹配
                        if lower_value == old_class.lower():
                            # 替换字典中的值为新类别名称
                            obj[key] = new_class
                            # 标记已进行修改
                            modified = True
                            # 如果启用详细模式,打印替换信息
                            if VERBOSE:
                                print(f"替换: {key} = {new_class}")

            # 如果当前值是字典或列表类型,递归处理该值
            if isinstance(value, (dict, list)):
                # 递归调用查找替换函数处理嵌套对象
                sub_modified = find_and_replace(value, class_mapping, case_sensitive)
                # 如果子对象有修改,更新整体修改标志
                modified = modified or sub_modified

                # 如果当前处理的对象是列表类型
    elif isinstance(obj, list):
        # 遍历列表中的每个元素
        for i, item in enumerate(obj):
            # 如果元素是字典或列表类型,递归处理该元素
            if isinstance(item, (dict, list)):
                # 递归调用查找替换函数处理列表元素
                sub_modified = find_and_replace(item, class_mapping, case_sensitive)
                # 如果子对象有修改,更新整体修改标志
                modified = modified or sub_modified

                # 返回是否进行了任何修改的标志
    return modified


def process_json_file(input_path, output_path, class_mapping, case_sensitive=True, verbose=True):
    """
    处理单个JSON文件,替换其中的多个类别名称

    参数:
    input_path (str): 输入文件路径
    output_path (str): 输出文件路径
    class_mapping (dict): 类别映射字典
    case_sensitive (bool): 是否区分大小写
    verbose (bool): 是否显示详细信息

    返回:
    bool: 文件是否被修改
    """
    try:
        # 如果启用详细模式,打印当前正在处理的文件路径
        if verbose:
            print(f"\n处理文件: {input_path}")

        # 以只读模式打开输入JSON文件并加载其内容
        with open(input_path, 'r', encoding='utf-8') as f:
            data = json.load(f)

        # 调用递归查找替换函数处理JSON数据
        modified = find_and_replace(data, class_mapping, case_sensitive)

        # 如果数据被修改
        if modified:
            # 如果启用详细模式,打印文件已修改并将保存的信息
            if verbose:
                print(f"文件已修改,保存到: {output_path}")

            # 以写入模式打开输出文件,将修改后的JSON数据写入
            with open(output_path, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=2)
            # 返回文件已修改的标志
            return True
        else:
            # 如果启用详细模式,打印未找到需要修改的类别名称的信息
            if verbose:
                print("未找到需要修改的类别名称")

            # 文件未修改,直接将原文件内容复制到输出文件
            with open(input_path, 'r', encoding='utf-8') as src, open(output_path, 'w', encoding='utf-8') as dst:
                dst.write(src.read())
            # 返回文件未被修改的标志
            return False

    # 捕获并处理可能出现的异常
    except Exception as e:
        # 打印处理文件时出现的错误信息
        print(f"处理文件 {input_path} 时出错: {str(e)}")
        # 返回文件处理失败的标志
        return False


def batch_process_json_files(input_dir, output_dir, class_mapping, case_sensitive=True, verbose=True):
    """
    批量处理目录下的所有JSON文件,替换多个类别名称

    参数:
    input_dir (str): 输入目录
    output_dir (str): 输出目录
    class_mapping (dict): 类别映射字典
    case_sensitive (bool): 是否区分大小写
    verbose (bool): 是否显示详细信息
    """
    # 确保输出目录存在,如果不存在则创建
    os.makedirs(output_dir, exist_ok=True)

    # 初始化JSON文件列表
    json_files = []
    # 遍历输入目录及其子目录
    for root, _, files in os.walk(input_dir):
        # 遍历当前目录下的所有文件
        for file in files:
            # 如果文件是JSON文件(忽略大小写)
            if file.lower().endswith('.json'):
                # 将JSON文件的完整路径添加到文件列表
                json_files.append(os.path.join(root, file))

    # 如果未找到任何JSON文件,打印错误信息并返回
    if not json_files:
        print(f"错误: 在 {input_dir} 目录下未找到JSON文件")
        return

    # 初始化每个类别的修改次数统计字典
    class_modification_counts = {old_class: 0 for old_class in class_mapping}

    # 使用进度条处理每个JSON文件,显示处理进度
    modified_count = 0
    for json_file in tqdm(json_files, desc="处理JSON文件"):
        # 计算输出文件相对于输入目录的相对路径
        rel_path = os.path.relpath(json_file, input_dir)
        # 构建输出文件的完整路径
        output_file = os.path.join(output_dir, rel_path)

        # 确保输出文件所在的目录存在
        output_file_dir = os.path.dirname(output_file)
        os.makedirs(output_file_dir, exist_ok=True)

        # 处理当前JSON文件并获取是否修改的标志
        if process_json_file(json_file, output_file, class_mapping, case_sensitive, verbose):
            # 累加修改的文件数量
            modified_count += 1

    # 如果启用详细模式且有文件被修改,打印每个类别的修改统计信息
    if verbose and modified_count > 0:
        print("\n类别修改统计:")
        for old_class, new_class in class_mapping.items():
            print(f"  {old_class} -> {new_class}")

    # 打印处理结果摘要
    print(f"\n处理完成!共处理 {len(json_files)} 个JSON文件,其中 {modified_count} 个文件被修改。")


def main():
    """主函数:程序入口点"""
    # 打印批量处理JSON文件的开始信息
    print(f"开始批量处理JSON文件...")
    # 打印输入目录信息
    print(f"输入目录: {INPUT_DIR}")
    # 打印输出目录信息
    print(f"输出目录: {OUTPUT_DIR}")
    # 打印类别映射配置信息
    print(f"类别映射: {CLASS_MAPPING}")
    # 打印是否区分大小写的配置信息
    print(f"区分大小写: {CASE_SENSITIVE}")
    # 打印是否显示详细信息的配置信息
    print(f"显示详细信息: {VERBOSE}")

    # 调用批量处理函数开始处理JSON文件
    batch_process_json_files(INPUT_DIR, OUTPUT_DIR, CLASS_MAPPING, CASE_SENSITIVE, VERBOSE)


# 程序执行入口:当作为脚本直接运行时,调用main函数
if __name__ == "__main__":
    main()  # 程序从这里开始执行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

扶云云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值