Python-TypeError: 类型为“ int64”的对象不是可序列化的 JSON

我有一个数据框,存储商店名称和每日销售计数。我正在尝试使用下面的 Python 脚本将其插入到 Salesforce 中。

然而,我得到了以下错误:

TypeError: Object of type 'int64' is not JSON serializable

下面是数据框架的视图。

Storename,Count
Store A,10
Store B,12
Store C,5

我使用以下代码将其插入到 Salesforce。

update_list = []
for i in range(len(store)):
update_data = {
'name': store['entity_name'].iloc[i],
'count__c': store['count'].iloc[i]
}
update_list.append(update_data)


sf_data_cursor = sf_datapull.salesforce_login()
sf_data_cursor.bulk.Account.update(update_list)

当执行上面的最后一行时,我得到了错误。

我该怎么补救?

221159 次浏览

json不识别 NumPy 数据类型。在序列化对象之前,将该数字转换为 Python int:

'count__c': int(store['count'].iloc[i])

您可以定义自己的编码器来解决这个问题。

import json
import numpy as np


class NpEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, np.integer):
return int(obj)
if isinstance(obj, np.floating):
return float(obj)
if isinstance(obj, np.ndarray):
return obj.tolist()
return super(NpEncoder, self).default(obj)


# Your codes ....
json.dumps(data, cls=NpEncoder)

这可能是最后的响应,但最近我得到了同样的错误。经过大量的冲浪,这个解决方案帮助了我。

def myconverter(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()
elif isinstance(obj, datetime.datetime):
return obj.__str__()

json.dumps()中调用 myconverter,如下所示。 json.dumps('message', default=myconverter)

我会把我对这个戒指的回答作为一个更加稳定的版本@JieYang 的 好办法

我的解决办法

numpyencoder 储存库

from numpyencoder import NumpyEncoder


numpy_data = np.array([0, 1, 2, 3])


with open(json_file, 'w') as file:
json.dump(numpy_data, file, indent=4, sort_keys=True,
separators=(', ', ': '), ensure_ascii=False,
cls=NumpyEncoder)

崩溃

如果你深入研究 numpyencoder/numpyencoder.py文件中的 Hmallen 的代码,你会发现它与@JieYang 的回答非常相似:


class NumpyEncoder(json.JSONEncoder):
""" Custom encoder for numpy data types """
def default(self, obj):
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)


elif isinstance(obj, (np.float_, np.float16, np.float32, np.float64)):
return float(obj)


elif isinstance(obj, (np.complex_, np.complex64, np.complex128)):
return {'real': obj.real, 'imag': obj.imag}


elif isinstance(obj, (np.ndarray,)):
return obj.tolist()


elif isinstance(obj, (np.bool_)):
return bool(obj)


elif isinstance(obj, (np.void)):
return None


return json.JSONEncoder.default(self, obj)

一个非常简单的数字编码器可以实现类似的结果更一般。

注意,这里使用了 np.generic类(大多数 np 类是从中继承的)并使用了 a.item()方法。

如果要编码的对象不是 numpy 实例,那么 json 序列化器将继续正常运行。这对于包含一些数字对象和一些其他类对象的字典是理想的。

import json
import numpy as np


def np_encoder(object):
if isinstance(object, np.generic):
return object.item()


json.dumps(obj, default=np_encoder)

如果您有这个错误

TypeError: 类型为“ int64”的对象不是可序列化的 JSON

您可以使用 int dtype 将这些特定列更改为 float64,例如:

df = df.astype({'col1_int':'float64', 'col2_int':'float64', etc..})

Float64在 Google 电子表格中写得很好

如果要序列化一个数字数组,可以简单地使用 ndarray.tolist()方法。

来自 笨手笨脚的医生,

a.tolist()list(a)几乎相同,只是 tolist将 numpy 标量更改为 Python 标量

In [1]: a = np.uint32([1, 2])


In [2]: type(list(a)[0])
Out[2]: numpy.uint32


In [3]: type(a.tolist()[0])
Out[3]: int

如果您可以控制 DataFrame的创建,您可以通过将 dtype设置为 object来强制它对值使用标准 Python 类型(例如 int而不是 numpy.int64) :

df = pd.DataFrame(data=some_your_data, dtype=object)

明显的缺点是性能低于原始数据类型。但我喜欢这个解决方案 tbh,它真的很简单,消除了所有可能的类型问题。不需要给 ORM 或 json任何提示。

我把垃圾装上车就成功了。

密码 :

import json

json.loads(json.dumps(your_df.to_dict()))

update_data = {
'name': str(store['entity_name'].iloc[i]),
'count__c': str(store['count'].iloc[i])
}

实际上,不需要编写一个编码器,只需要在调用 json.dumps函数时将默认值改为 str即可,这样就可以在一行代码中处理大多数类型:

json.dumps(data, default=str)

来自 json.dumpsjson.dump的文档: Https://docs.python.org/3/library/json.html#json.dump

如果指定了,默认值应该是为无法序列化的对象调用的函数。它应该返回对象的 JSON 可编码版本或引发 TypeError。如果未指定,则引发 TypeError。

因此,调用 str将 numpy 类型(如 numpy int 或 numpy float)转换为可由 json 解析的字符串。如果有数字数组或范围,则必须首先将它们转换为列表。在这种情况下,写一个编码器,如杨建议的可能是一个更合适的解决方案。

这篇文章中有很好的答案,适用于大多数情况。然而,我需要一个适用于所有数字类型(例如复数)并返回 Json 循规蹈矩(例如逗号作为列表分隔符)的解决方案。

麻烦的解决方案

另一种选择是在内部将 numpy 数组或值转换为字符串 numpy,即: np.array2string。这个选项应该非常健壮,您可以根据需要采用输出。

import sys
import numpy as np


def np_encoder(obj):
if isinstance(obj, (np.generic, np.ndarray)):
out = np.array2string(obj,
separator=',',
threshold=sys.maxsize,
precision=50,
floatmode='maxprec')
# remove whitespaces and '\n'
return out.replace(' ','').replace('\n','')


# example usage
data = np.array([0, 1+0j, 3.123, -1, 2, -5, 10], dtype=np.complex128)
json.dumps({'value': data[-1], 'array': data}, default=np_encoder)
# '{"value": "10.+0.j",
#   "array": "[0.+0.j, 1.+0.j, 3.123+0.j, -1.+0.j, 2.+0.j, -5.+0.j, 10.+0.j]"}'

评论:

  • 要符合 json 列表,分隔符必须设置为 separator=','
  • threshold=sys.maxsize返回尽可能多的条目 新的触发汇总(...,)。
  • 还有其他参数 (precisionfloatmodeformatter,...)你可以根据需要采用你的输出。
  • 对于一个紧凑的 json,我删除了所有的空格和换行符(.replace(' ','').replace('\n',''))。

下面是一个处理 bools 和 NaN 值的版本(它们不属于 JSON 规范的一部分) ,作为 null

import json
import numpy as np


class NpJsonEncoder(json.JSONEncoder):
"""Serializes numpy objects as json."""


def default(self, obj):
if isinstance(obj, np.integer):
return int(obj)
elif isinstance(obj, np.bool_):
return bool(obj)
elif isinstance(obj, np.floating):
if np.isnan(obj):
return None  # Serialized as JSON null.
return float(obj)
elif isinstance(obj, np.ndarray):
return obj.tolist()
else:
return super().default(obj)


# Your code ...
json.dumps(data, cls=NpEncoder)