嵌套defaultdict含NumPy数组的JSON序列化问题(NumPy 2.0)
解决嵌套defaultdict中NumPy类型的JSON序列化问题
你的核心问题是自定义转换函数未被应用到整个嵌套结构,导致json.dump先遇到无法序列化的NumPy数组直接报错。以下是两种可靠的解决方法:
方法一:提前递归转换整个数据结构
先遍历嵌套的defaultdict、列表等结构,将所有NumPy类型转为Python基础类型,同时把defaultdict转为普通dict(JSON原生支持普通字典)。
完善递归转换函数
import numpy as np from collections import defaultdict def make_json_serializable(obj): # 把defaultdict转为普通字典 if isinstance(obj, defaultdict): obj = dict(obj) # 递归处理列表中的每个元素 if isinstance(obj, list): return [make_json_serializable(item) for item in obj] # NumPy数组转为Python列表 if isinstance(obj, np.ndarray): return obj.tolist() # NumPy标量类型转为Python原生数值类型 if isinstance(obj, (np.int_, np.intc, np.intp, np.int8, np.int16, np.int32, np.int64, np.uint8, np.uint16, np.uint32, np.uint64)): return int(obj) if isinstance(obj, (np.float_, np.float16, np.float32, np.float64)): return float(obj) # 处理np.nan(JSON不原生支持NaN,可转为None或保留float('nan'),按需选择) if isinstance(obj, float) and np.isnan(obj): return None # 原生Python类型直接返回 return obj
使用方式
import json # 先转换整个数据结构为可序列化格式 serializable_data = make_json_serializable(data_to_save) # 写入JSON文件 with open("simulation_results.json", "w") as f: json.dump(serializable_data, f, indent=4)
方法二:利用json.dump的default参数动态处理
不需要提前转换整个结构,而是让json.dump在遇到无法序列化的类型时,自动调用你的转换逻辑,同时处理defaultdict和NumPy类型。
实现default回调函数
import json import numpy as np from collections import defaultdict def json_serializer(obj): # 处理NumPy数组 if isinstance(obj, np.ndarray): return obj.tolist() # 处理NumPy标量 if isinstance(obj, (np.int_, np.intc, np.intp, np.int8, np.int16, np.int32, np.int64, np.uint8, np.uint16, np.uint32, np.uint64)): return int(obj) if isinstance(obj, (np.float_, np.float16, np.float32, np.float64)): return float(obj) # 处理np.nan if isinstance(obj, float) and np.isnan(obj): return None # 处理defaultdict if isinstance(obj, defaultdict): return dict(obj) # 未知类型抛出错误 raise TypeError(f"无法序列化类型: {type(obj).__name__}")
使用方式
with open("simulation_results.json", "w") as f: json.dump(data_to_save, f, default=json_serializer, indent=4)
方案选择
- 方法一适合需要先验证转换后数据结构、或后续还要复用转换后数据的场景;
- 方法二更节省内存,适合处理大型仿真结果(无需提前复制整个数据结构)。
内容的提问来源于stack exchange,提问作者STATTHINGY TRENTON
相关产品推荐
相关产品推荐

