NumPy 数组不可序列化为 JSON

2025-01-07 08:44:00
admin
原创
163
摘要:问题描述:创建 NumPy 数组并将其保存为 Django 上下文变量后,加载网页时收到以下错误:array([ 0, 239, 479, 717, 952, 1192, 1432, 1667], dtype=int64) is not JSON serializable 这意味着什么?解决方案 ...

问题描述:

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

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

这意味着什么?


解决方案 1:

我经常“jsonify”np.arrays。首先尝试在数组上使用“.tolist()”方法,如下所示:

import numpy as np
import codecs, json 

a = np.arange(10).reshape(2,5) # a 2 by 5 array
b = a.tolist() # nested lists with same data, indices
file_path = "/path.json" ## your path variable
json.dump(b, codecs.open(file_path, 'w', encoding='utf-8'), 
          separators=(',', ':'), 
          sort_keys=True, 
          indent=4) ### this saves the array in .json format

为了“取消 JSON 化”数组,请使用:

obj_text = codecs.open(file_path, 'r', encoding='utf-8').read()
b_new = json.loads(obj_text)
a_new = np.array(b_new)

解决方案 2:

将 numpy.ndarray 或任何嵌套列表组合存储为 JSON。

class NumpyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.ndarray):
            return obj.tolist()
        return super().default(obj)

a = np.array([[1, 2, 3], [4, 5, 6]])
print(a.shape)
json_dump = json.dumps({'a': a, 'aa': [2, (2, 3, 4), a], 'bb': [2]}, 
                       cls=NumpyEncoder)
print(json_dump)

将会输出:

(2, 3)
{"a": [[1, 2, 3], [4, 5, 6]], "aa": [2, [2, 3, 4], [[1, 2, 3], [4, 5, 6]]], "bb": [2]}

要从 JSON 恢复:

json_load = json.loads(json_dump)
a_restored = np.asarray(json_load["a"])
print(a_restored)
print(a_restored.shape)

将会输出:

[[1 2 3]
 [4 5 6]]
(2, 3)

解决方案 3:

如果字典中嵌套了 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)

感谢这个家伙。

解决方案 4:

你可以使用Pandas:

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

解决方案 5:

使用json.dumps default关键字:

default 应该是一个针对无法序列化的对象调用的函数。......或者引发 TypeError

default函数中检查对象是否来自模块 numpy,如果是,则使用ndarray.tolistndarray.item用于任何其他 numpy 特定类型。

import numpy as np

def default(obj):
    if type(obj).__module__ == np.__name__:
        if isinstance(obj, np.ndarray):
            return obj.tolist()
        else:
            return obj.item()
    raise TypeError('Unknown type:', type(obj))

dumped = json.dumps(data, default=default)

解决方案 6:

默认情况下不支持此功能,但您可以轻松实现!如果您想要返回完全相同的数据,则需要对以下几项进行编码:

  • 数据本身,您可以obj.tolist()像@travelingbones 提到的那样获取。有时这可能就足够了。

  • 数据类型。我觉得这在很多情况下都很重要。

  • 维度(不一定是二维),如果您假设输入确实始终是一个“矩形”网格,则可以从上面得出。

  • 内存顺序(行优先或列优先)。这通常并不重要,但有时却很重要(例如性能),那么为什么不保存所有内容呢?

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

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

pip install json-tricks

然后

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))

解决方案 7:

我在包含一些 numpy.ndarrays 的嵌套字典中遇到了类似的问题。

def jsonify(data):
    json_data = dict()
    for key, value in data.iteritems():
        if isinstance(value, list): # for lists
            value = [ jsonify(item) if isinstance(item, dict) else item for item in value ]
        if isinstance(value, dict): # for nested lists
            value = jsonify(value)
        if isinstance(key, int): # if key is integer: > to string
            key = str(key)
        if type(value).__module__=='numpy': # if value is numpy.*: > to python list
            value = value.tolist()
        json_data[key] = value
    return json_data

解决方案 8:

您还可以使用default参数,例如:

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

json.dump(data, default=myconverter)

解决方案 9:

如果其他人的代码(例如模块)正在执行 ,则其他答案将不起作用json.dumps()。这种情况经常发生,例如,Web 服务器会自动将其返回响应转换为 JSON,这意味着我们不能总是更改 的参数json.dump()

这个答案解决了这个问题,并且基于一个适用于任何第三方类(不仅仅是numpy)的(相对)新的解决方案。

结论

pip install 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]}'

解决方案 10:

此外,有关 Python 中的列表与数组的一些非常有趣的信息 ~> Python 列表与数组 - 何时使用?

值得注意的是,一旦我将数组转换为列表,然后将其保存在 JSON 文件中,无论如何,在我现在的部署中,一旦我读取该 JSON 文件以供稍后使用,我就可以继续以列表形式使用它(而不是将其转换回数组)。

实际上(在我看来)在屏幕上以列表(逗号分隔)而不是数组(非逗号分隔)的形式看起来更美观。

使用上面的@travelingbones 的 .tolist() 方法,我一直这样使用(捕获了我发现的一些错误):

保存词典

def writeDict(values, name):
    writeName = DIR+name+'.json'
    with open(writeName, "w") as outfile:
        json.dump(values, outfile)

阅读字典

def readDict(name):
    readName = DIR+name+'.json'
    try:
        with open(readName, "r") as infile:
            dictValues = json.load(infile)
            return(dictValues)
    except IOError as e:
        print(e)
        return('None')
    except ValueError as e:
        print(e)
        return('None')

希望这有帮助!

解决方案 11:

使用 NumpyEncoder 它将成功处理 json 转储。不会抛出 - NumPy 数组不是 JSON 可序列化的

import numpy as np
import json
from numpyencoder import NumpyEncoder
arr = array([   0,  239,  479,  717,  952, 1192, 1432, 1667], dtype=int64) 
json.dumps(arr,cls=NumpyEncoder)

解决方案 12:

这是一个对我有用的实现,它删除了所有的 nan(假设这些是简单对象(列表或字典)):

from numpy import isnan

def remove_nans(my_obj, val=None):
    if isinstance(my_obj, list):
        for i, item in enumerate(my_obj):
            if isinstance(item, list) or isinstance(item, dict):
                my_obj[i] = remove_nans(my_obj[i], val=val)

            else:
                try:
                    if isnan(item):
                        my_obj[i] = val
                except Exception:
                    pass

    elif isinstance(my_obj, dict):
        for key, item in my_obj.iteritems():
            if isinstance(item, list) or isinstance(item, dict):
                my_obj[key] = remove_nans(my_obj[key], val=val)

            else:
                try:
                    if isnan(item):
                        my_obj[key] = val
                except Exception:
                    pass

    return my_obj

解决方案 13:

这是一个不同的答案,但这可能有助于帮助那些试图保存数据然后再次读取的人。

有比 pickle 更快、更简单的 hickle。

我尝试在 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' )

解决方案 14:

可以执行简单的 for 循环并检查类型:

with open("jsondontdoit.json", 'w') as fp:
    for key in bests.keys():
        if type(bests[key]) == np.ndarray:
            bests[key] = bests[key].tolist()
            continue
        for idx in bests[key]:
            if type(bests[key][idx]) == np.ndarray:
                bests[key][idx] = bests[key][idx].tolist()
    json.dump(bests, fp)
    fp.close()

解决方案 15:

TypeError: array([[0.46872085, 0.67374235, 1.0218339 , 0.13210179, 0.5440686 , 0.9140083 , 0.58720225, 0.2199381 ]], dtype=float32) 不是 JSON 可序列化的

当我尝试将数据列表传递给 model.predict() 时抛出了上述错误,而我期望得到 json 格式的响应。

> 1        json_file = open('model.json','r')
> 2        loaded_model_json = json_file.read()
> 3        json_file.close()
> 4        loaded_model = model_from_json(loaded_model_json)
> 5        #load weights into new model
> 6        loaded_model.load_weights("model.h5")
> 7        loaded_model.compile(optimizer='adam', loss='mean_squared_error')
> 8        X =  [[874,12450,678,0.922500,0.113569]]
> 9        d = pd.DataFrame(X)
> 10       prediction = loaded_model.predict(d)
> 11       return jsonify(prediction)

但幸运的是找到了解决抛出错误的提示对象的序列化仅适用于以下转换映射应按以下方式进行对象 - 字典数组 - 列表字符串 - 字符串整数 - 整数

如果你向上滚动看到行号 10 prediction = loaded_model.predict(d),其中此行代码生成类型为 array datatype 的输出,当你尝试将 array 转换为 json 格式时,这是不可能的

最后我找到了解决方案,只需按照以下代码行将获得的输出转换为类型列表即可

预测 = loaded_model.predict(d)

listtype = prediction.tolist() 返回 jsonify(listtype)

Bhoom!终于得到了预期的输出,
在此处输入图片描述

解决方案 16:

我遇到了同样的问题,但略有不同,因为我的值来自 float32 类型,所以我将它们转换为简单的 float(值)。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2941  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1803  
  PLM(产品生命周期管理)系统在企业的产品研发、生产与管理过程中扮演着至关重要的角色。然而,在实际运行中,资源冲突是经常会遇到的难题。资源冲突可能导致项目进度延迟、成本增加以及产品质量下降等一系列问题,严重影响企业的效益与竞争力。因此,如何有效应对PLM系统中的资源冲突,成为众多企业关注的焦点。接下来,我们将详细探讨5...
plm项目管理系统   31  
  敏捷项目管理与产品生命周期管理(PLM)的融合,正成为企业在复杂多变的市场环境中提升研发效率、增强竞争力的关键举措。随着技术的飞速发展和市场需求的快速更迭,传统的研发流程面临着诸多挑战,而将敏捷项目管理理念融入PLM,有望在2025年实现研发流程的深度优化,为企业创造更大的价值。理解敏捷项目管理与PLM的核心概念敏捷项...
plm项目   31  
  模块化设计在现代产品开发中扮演着至关重要的角色,它能够提升产品开发效率、降低成本、增强产品的可维护性与可扩展性。而产品生命周期管理(PLM)系统作为整合产品全生命周期信息的关键平台,对模块化设计有着强大的支持能力。随着技术的不断发展,到 2025 年,PLM 系统在支持模块化设计方面将有一系列令人瞩目的技术实践。数字化...
plm软件   28  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用