一、类别名称修改前后对比
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() # 程序从这里开始执行