Python - TypeError: объект типа int64 не сериализуемый JSON

У меня есть фрейм данных, в котором хранится название магазина и количество ежедневных продаж. Я пытаюсь вставить это в Salesforce, используя скрипт Python ниже. Однако я получаю следующую ошибку:

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)

Получение ошибки, когда выполняется последняя строка выше. Может ли кто-нибудь помочь исправить это? Спасибо..

Звонок range подозрительный. Вы берете len(store) и оборачиваете его в кортеж, а затем вызываете range для этого кортежа. Если вы удалите одну скобку, исправит ли это код? То есть попробуйте это: for i in range(len(store)):.

Tim Johns 18.06.2018 22:00

@TimJohns Пара скобок вокруг числа не делает его кортежем. (34) - это по-прежнему число 34. Но (34,) - это кортеж.

DYZ 18.06.2018 22:04

@DyZ Хороший момент, я не осознавал, что круглые скобки с одним аргументом обрабатываются иначе, чем при наличии нескольких аргументов.

Tim Johns 18.06.2018 22:13

@TimJohns Парни не имеют значения. a=34, также является кортежем

Sebastian Wozny 20.02.2020 16:27

Есть открытый отчет об этой проблеме: bugs.python.org/issue24313

Mihai Capotă 22.07.2020 22:59
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
112
5
117 292
10

Ответы 10

json не распознает типы данных NumPy. Преобразуйте номер в Python int перед сериализацией объекта:

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

Спасибо большое, дружище!

kuntam robo 26.05.2021 12:04

Другой вариант - при создании фрейма данных использовать dtype=str

Например, если вы загрузили store из файла csv:

import pandas as pd
store = pd.read_csv('store.csv', dtype=str)

Затем все имеет тип str, который можно сериализовать в json.

Это ужасно. Не делай этого. Абсолютный ужасный совет.

Henry Henrinson 29.07.2020 16:05

Почему? Это допустимый подход, и он также позволяет решить проблему, заключающуюся в том, что иногда int64 недостаточно велик для представления входного числа. Более того, в JSON большие числа также часто представлены в виде строк. Поэтому, если вопрос заключается в том, чтобы просто преобразовать входной CSV в JSON с наименьшим количеством преобразований, сделанных на этом этапе, это хороший подход.

Mitar 15.12.2020 20:23

Голосование вниз, потому что этот ответ не преобразуется должным образом в соответствующий тип json. Он просто предлагает хакерское решение, которое потребует дополнительной постобработки после сериализации json.

conmak 18.12.2020 16:46

Вы можете определить свой собственный кодировщик для решения этой проблемы.

import json
import numpy as np

class NpEncoder(json.JSONEncoder):
    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()
        else:
            return super(NpEncoder, self).default(obj)

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

работает, но результат - строка, без слов с форматированными данными

Ivan Camilito Ramirez Verdes 22.09.2019 22:09

@IvanCamilitoRamirezVerdes Это именно то, что я искал, поэтому мне это очень помогло. Мне также нравится удобочитаемость добавления класса кодирования в функцию json.dumps.

Jason R Stevens CFA 20.05.2020 03:54

у меня почему-то не сработало ... поддерживает ли это рекурсивные вызовы?

adir abargil 02.12.2020 15:43

Еще нужно было добавить elif isinstance(obj, np.bool_): return bool(obj)

James McKeown 08.02.2021 20:32

Это может быть поздний ответ, но недавно я получил ту же ошибку. После долгого серфинга это решение мне помогло.

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

Вызовите myconverter в json.dumps(), как показано ниже. json.dumps('message', default=myconverter)

или вы можете использовать elif isinstance(obj, (datetime.date, datetime.datetime)): return obj.isoformat()

Colin Anthony 16.09.2020 10:23

Я брошу свой ответ кольцу как более стабильную версию отличное решение @Jie Yang.

Мое решение

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, вы увидите, что он очень похож на ответ @Jie Yang:


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)

Очень простой кодировщик numpy может достичь аналогичных результатов в более общем плане.

Обратите внимание, что здесь используется класс np.generic (от которого наследуется большинство классов np) и метод a.item().

Если объект для кодирования не является экземпляром numpy, сериализатор json продолжит работу в обычном режиме. Это идеально подходит для словарей с несколькими объектами numpy и некоторыми другими объектами классов.

import json
import numpy as np

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

json.dumps(obj, default=np_encoder)

Кратко и лаконично.

Vasantha Ganesh 21.04.2021 09:53

Это не сработало, когда у меня был массив с нулевой яркостью, такой как np.array(1). Простое исправление: if isinstance(object, (np.generic, np.ndarray))

Michael 12.05.2021 13:39

Если у вас есть эта ошибка

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

Вы можете изменить эти конкретные столбцы с помощью int dtype на float64, например:

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

Float64 отлично записывается в Google Spreadsheets

Если вы собираетесь сериализовать массив numpy, вы можете просто использовать метод ndarray.tolist().

От numpy docs,

a.tolist() is almost the same as list(a), except that tolist changes numpy scalars to Python scalars

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, вы можете заставить его использовать стандартные типы Python для значений (например, int вместо numpy.int64), установив для dtype значение object:

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

Очевидным недостатком является то, что вы получаете меньшую производительность, чем с примитивными типами данных. Но мне нравится это решение, оно действительно простое и устраняет все возможные проблемы типов. Не надо никаких подсказок ORM или json.

У меня получилось заставить работать с загрузкой дампа.

Код:

import json

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

Другие вопросы по теме