API返回JSON日志过长,求支持任意嵌套的递归精简方案
递归实现任意嵌套的JSON日志精简方案
我完全懂你现在的困扰——长JSON日志塞满文件,两层嵌套的实现又显得笨拙又不够用。这里给你一个递归版的解决方案,能轻松处理任意深度的嵌套结构,还能保证原数据丝毫不被改动(毕竟日志场景可不能碰生产数据)。
实现代码
这个实现会递归遍历每一层结构,严格按照你要求的规则精简数组和字典,其他基础类型(字符串、数字等)直接保留:
import copy def log_reducer(data): # 处理列表类型:长度≥5时保留前2、后2个元素,中间用"..."占位 if isinstance(data, list): if len(data) >= 5: reduced_items = [log_reducer(item) for item in data[:2]] reduced_items.append("...") reduced_items.extend([log_reducer(item) for item in data[-2:]]) return reduced_items else: return [log_reducer(item) for item in data] # 处理字典类型:键值对≥4时保留前4个,添加"...": "..."占位 elif isinstance(data, dict): dict_items = list(data.items()) if len(dict_items) >= 4: reduced_dict = {} # 递归处理前4个键值对 for key, value in dict_items[:4]: reduced_dict[key] = log_reducer(value) reduced_dict["..."] = "..." return reduced_dict else: return {key: log_reducer(value) for key, value in dict_items} # 基础类型直接返回,用deepcopy避免修改原数据(可选,追求性能可去掉) else: return copy.deepcopy(data)
测试你的示例
把你提供的测试代码跑一遍,看看实际效果:
test_json = {"works": [1, 2, 3, 4, 5, 6], "not_affected": [{"1": "1", "2": "2", "3": "3", "4": "4", "5": "5"}], "1": "1", "2": "2", "3": "3", "removed": "removed" } print("original", test_json) reduced_log = log_reducer(test_json) print("reduced", reduced_log) print("original", test_json) reduced_log = log_reducer([test_json]) # <- 增加嵌套深度测试 print("reduced", reduced_log)
输出结果
original {'works': [1, 2, 3, 4, 5, 6], 'not_affected': [{'1': '1', '2': '2', '3': '3', '4': '4', '5': '5'}], '1': '1', '2': '2', '3': '3', 'removed': 'removed'} reduced {'works': [1, 2, '...', 5, 6], 'not_affected': [{'1': '1', '2': '2', '3': '3', '4': '4', '...': '...'}], '1': '1', '2': '2', '...': '...'} original {'works': [1, 2, 3, 4, 5, 6], 'not_affected': [{'1': '1', '2': '2', '3': '3', '4': '4', '5': '5'}], '1': '1', '2': '2', '3': '3', 'removed': 'removed'} reduced [{'works': [1, 2, '...', 5, 6], 'not_affected': [{'1': '1', '2': '2', '3': '3', '4': '4', '...': '...'}], '1': '1', '2': '2', '...': '...'}]
可以看到,不管嵌套多少层,数组和字典都按规则被精简了,而且原数据完全没被改动,符合日志可视化的需求。
可选优化:让规则更灵活
如果之后需要调整保留的元素数量(比如数组保留前3后3,字典保留前5个),可以把参数做成可配置的:
import copy def log_reducer(data, list_keep=2, dict_keep=4): if isinstance(data, list): # 当列表长度超过「2*保留数+1」时才精简(比如保留2个时,长度≥5触发) if len(data) >= 2 * list_keep + 1: reduced_items = [log_reducer(item, list_keep, dict_keep) for item in data[:list_keep]] reduced_items.append("...") reduced_items.extend([log_reducer(item, list_keep, dict_keep) for item in data[-list_keep:]]) return reduced_items else: return [log_reducer(item, list_keep, dict_keep) for item in data] elif isinstance(data, dict): dict_items = list(data.items()) if len(dict_items) >= dict_keep + 1: reduced_dict = {} for key, value in dict_items[:dict_keep]: reduced_dict[key] = log_reducer(value, list_keep, dict_keep) reduced_dict["..."] = "..." return reduced_dict else: return {key: log_reducer(value, list_keep, dict_keep) for key, value in dict_items} else: return copy.deepcopy(data)
调用时就可以自定义规则:log_reducer(test_json, list_keep=3, dict_keep=5)
关于现成库
其实这种定制化的日志精简需求,现成库很难完全匹配你的规则。不过如果只是需要通用的JSON压缩,可以看看json-truncate这类工具,但它们的规则不一定贴合你的场景。自己写递归实现反而更灵活,代码量也小,容易维护和调整。
内容的提问来源于stack exchange,提问作者c8999c 3f964f64
相关产品推荐
相关产品推荐

