在创建NumPy数组后,并将其保存为Django上下文变量,我在加载网页时收到以下错误:

array([   0,  239,  479,  717,  952, 1192, 1432, 1667], dtype=int64) is not JSON serializable

这是什么意思?


当前回答

如果你在字典中嵌套了numpy数组,我发现了最好的解决方案:

import json
import numpy as np

class NumpyEncoder(json.JSONEncoder):
    """ Special json encoder for numpy types """
    def default(self, obj):
        if isinstance(obj, np.integer):
            return int(obj)
        elif isinstance(obj, np.floating):
            return float(obj)
        elif isinstance(obj, np.ndarray):
            return obj.tolist()
        return json.JSONEncoder.default(self, obj)

dumped = json.dumps(data, cls=NumpyEncoder)

with open(path, 'w') as f:
    json.dump(dumped, f)

多亏了这个家伙。

其他回答

默认情况下不支持这一点,但是您可以很容易地让它工作!如果你想要返回完全相同的数据,有几个东西你需要编码:

数据本身,您可以通过obj.tolist()获得,如@travelingbones所述。有时这可能已经足够好了。 数据类型。我觉得这在很多情况下很重要。 维度(不一定是2D),如果你假设输入确实总是一个“矩形”网格,可以从上面得到。 内存顺序(行或列为主)。这通常并不重要,但有时很重要(例如性能),所以为什么不保存所有内容呢?

此外,你的numpy数组可以是你的数据结构的一部分,例如,你有一个包含一些矩阵的列表。为此,你可以使用一个自定义编码器,基本上做上述。

这应该足以实现解决方案。或者你可以使用json-tricks,它可以做到这一点(并支持各种其他类型)(免责声明:是我做的)。

pip install json-tricks

Then

data = [
    arange(0, 10, 1, dtype=int).reshape((2, 5)),
    datetime(year=2017, month=1, day=19, hour=23, minute=00, second=00),
    1 + 2j,
    Decimal(42),
    Fraction(1, 3),
    MyTestCls(s='ub', dct={'7': 7}),  # see later
    set(range(7)),
]
# Encode with metadata to preserve types when decoding
print(dumps(data))

你可以使用Pandas:

import pandas as pd
pd.Series(your_array).to_json(orient='values')

如果其他人的代码(例如模块)正在执行json.dumps(),其他答案将不起作用。这种情况经常发生,例如,web服务器自动将其返回响应转换为JSON,这意味着我们不能总是更改JSON .dump()的参数。 这个答案解决了这个问题,并且基于一个(相对)新的解决方案,适用于任何第三方类(不仅仅是numpy)。

TLDR

PIP安装json_fix

import json_fix # import this anytime before the JSON.dumps gets called
import json

# create a converter
import numpy
json.fallback_table[numpy.ndarray] = lambda array: array.tolist()

# no additional arguments needed: 
json.dumps(
   dict(thing=10, nested_data=numpy.array((1,2,3)))
)
#>>> '{"thing": 10, "nested_data": [1, 2, 3]}'

这是一个不同的答案,但这可能有助于那些试图保存数据然后再次读取的人。 有一种方法比泡菜更快更容易。 我试图保存并在pickle dump中阅读它,但在阅读时有很多问题,浪费了一个小时,尽管我正在用自己的数据创建一个聊天机器人,但仍然没有找到解决方案。

Vec_x和vec_y是numpy数组:

data=[vec_x,vec_y]
hkl.dump( data, 'new_data_file.hkl' )

然后你只需读取它并执行以下操作:

data2 = hkl.load( 'new_data_file.hkl' )

你也可以使用default参数,例如:

def myconverter(o):
    if isinstance(o, np.float32):
        return float(o)

json.dump(data, default=myconverter)