欢迎光临
我们一直在努力

python报错TypeError: Object of type ndarray is not JSON serializable

在进行科学计算、数据分析或构建基于Python的数据API服务时,我们经常会用到强大的NumPy库。然而,当我们需要将包含NumPy数组(ndarray)的数据结构转换为JSON格式以便通过网络传输或写入配置文件时,Python内置的json库通常会抛出TypeError: Object of type ndarray is not JSON serializable的错误。

为什么会发生这个错误?

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。JSON标准只支持以下基本数据类型:字符串、数字、布尔值、列表(数组)、对象(字典)和null。NumPy的ndarray对象是Python对象,但它不属于JSON标准支持的原生类型,因此json.dumps()不知道如何将其转换为有效的JSON值。

环境准备

确保您的环境中安装了NumPy和Python标准库。

pip install numpy

演示错误现场

以下代码展示了触发此错误的常见场景:

import json
import numpy as np

# 创建一个包含 ndarray 的字典
data_with_numpy = {
    "user_id": 101,
    "feature_vector": np.array([0.5, 1.2, 3.7, 9.0]),
    "status": "ready"
}

# 尝试序列化,这将导致 TypeError
try:
    json_output = json.dumps(data_with_numpy)
except TypeError as e:
    print(f"捕获到错误: {e}")
    # 输出: 捕获到错误: Object of type ndarray is not JSON serializable

解决方法一:使用 .tolist() 转换(最简单的方法)

如果你只需要转换少数几个ndarray对象,最直接的方法是使用NumPy数组自带的.tolist()方法。这个方法会将NumPy数组递归地转换为标准的Python列表(list)。

import json
import numpy as np

data_fixed_1 = {
    "user_id": 101,
    # 关键步骤:使用 .tolist() 转换
    "feature_vector": np.array([0.5, 1.2, 3.7, 9.0]).tolist(),
    "status": "ready"
}

json_output = json.dumps(data_fixed_1, indent=4)
print("\n--- 修复方法一结果 ---")
print(json_output)

解决方法二:创建自定义 JSON 编码器(推荐用于复杂应用)

如果你的应用程序或API返回的数据中,NumPy数组无处不在,手动调用.tolist()会变得繁琐。更优雅、更具扩展性的方法是创建一个继承自json.JSONEncoder的自定义编码器。

通过重写default方法,我们可以告诉json.dumps在遇到ndarray类型时应该如何处理它。

import json
import numpy as np

# 1. 定义自定义 JSON 编码器
class NumpyEncoder(json.JSONEncoder):
    def default(self, obj):
        # 检查对象是否为 ndarray 类型
        if isinstance(obj, np.ndarray):
            # 如果是,将其转换为标准的 Python 列表
            return obj.tolist()
        # 也可以处理其他 NumPy 特定的标量类型,如 np.float32
        if isinstance(obj, (np.generic, np.number)):
            return obj.item()

        # 如果是其他未处理的类型,则调用父类的 default 方法
        return json.JSONEncoder.default(self, obj)

# 示例数据 (包含多维数组)
data_fixed_2 = {
    "matrix_data": np.array([[10, 20], [30, 40]]),
    "timestamp": np.float64(1678886400.0),
    "metadata": [1, 2]
}

# 2. 使用自定义编码器进行序列化
json_output_custom = json.dumps(
    data_fixed_2,
    cls=NumpyEncoder, # 指定我们自定义的编码器
    indent=4
)

print("\n--- 修复方法二结果 (使用自定义编码器) ---")
print(json_output_custom)

输出结果示例 (修复方法二):

{
    "matrix_data": [
        [
            10,
            20
        ],
        [
            30,
            40
        ]
    ],
    "timestamp": 1678886400.0,
    "metadata": [
        1,
        2
    ]
}

总结

解决TypeError: Object of type ndarray is not JSON serializable的核心思想是将非标准类型转换为JSON支持的基本类型。对于NumPy数组,最可靠的方法是使用.tolist()将其转换为Python列表。在大型项目或Web框架(如Flask/Django API)中,通过定义一个全局的NumpyEncoder并将其作为cls参数传递给json.dumps,可以实现数据序列化的自动化和标准化。

【本站文章皆为原创,未经允许不得转载】:汤不热吧 » python报错TypeError: Object of type ndarray is not JSON serializable
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址