it-roy-ru.com

Массив NumPy не поддерживает сериализацию в формате JSON

После создания массива NumPy и сохранения его как контекстной переменной Django при загрузке веб-страницы появляется следующая ошибка:

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

Что это значит?

160
Karnivaurus

Я регулярно "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

Для "unjsonify" массива используйте:

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

Сохраните как JSON numpy.ndarray или любую композицию вложенного списка.

class NumpyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.ndarray):
            return obj.tolist()
        return json.JSONEncoder.default(self, 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)
126
karlB

Вы можете использовать Панды :

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

Я нашел лучшее решение, если вы вложили в словарь вложенные массивы:

import json
import numpy as np

class NumpyEncoder(json.JSONEncoder):
    """ Special json encoder for numpy 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.ndarray,)): #### This is the fix
            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)

Спасибо этот парень .

24
tsveti_iko

Некоторые из других кодировщиков NumPy кажутся слишком многословными.

проверьте, является ли объект if из модуля numpy, если это так, либо используйте ndarray.tolist для ndarray, либо используйте .item для любого другого конкретного numpy типа.

Используйте json.dumpsdefault kwarg:

default должна быть функция, которая вызывается для объектов, которые иначе не могут быть сериализованы.

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

Это не поддерживается по умолчанию, но вы можете сделать это довольно легко! Есть несколько вещей, которые вы захотите закодировать, если хотите вернуть те же самые данные:

  • Сами данные, которые вы можете получить с помощью obj.tolist(), как упомянуто @travelingbones. Иногда это может быть достаточно хорошо.
  • Тип данных. Я чувствую, что это важно в некоторых случаях.
  • Измерение (не обязательно 2D), которое может быть получено из вышеприведенного, если вы предполагаете, что ввод действительно всегда является "прямоугольной" сеткой.
  • Порядок памяти (строка или столбец). Это не часто имеет значение, но иногда это имеет значение (например, производительность), так почему бы не сохранить все?

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

Этого должно быть достаточно для реализации решения. Или вы можете использовать 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))
4
Mark

У меня была похожая проблема с вложенным словарём с несколькими 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
3
JLT

Вы также можете использовать аргумент default, например:

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

json.dump(data, default=myconverter)
3
steco

Может сделать простой цикл с проверкой типов:

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()
1
Robert GRZELKA

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)

Но, к счастью, нашла подсказку, чтобы разрешить ошибку, которая выдавала. Сериализация объектов применима только для следующего преобразования. Отображение должно выполняться следующим образом: объект - dict массив - список строк - строка целое число - целое число

Если вы прокрутите вверх, чтобы увидеть строку с номером 10pretion =loaded_model.predict (d), где эта строка кода генерировала выходные данные типа массива данных типа, при попытке преобразовать массив в формат json это невозможно

Наконец, я нашел решение, просто преобразовав полученный вывод в список типов с помощью следующих строк кода

предсказание = загруженная_модель.predict (d)
listtype = pretiontion.tolist () return jsonify (listtype)

Bhoom! наконец-то получил ожидаемый результат, enter image description here

1
Poornima Subramani Naidu

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

vec_x и vec_y являются массивами numpy:

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

Затем вы просто читаете его и выполняете операции:

data2 = hkl.load( 'new_data_file.hkl' )
1
KS HARSHA

Вот реализация, которая работает для меня и удалила все nans (при условии, что это простой объект (list или dict)):

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
1
Roei Bahumi

Кроме того, в Python ~> очень много интересной информации о списках и массивах) (список Python против массива - когда использовать?

Можно отметить, что как только я преобразую свои массивы в список перед сохранением его в файл JSON, в любом случае, в моем развертывании прямо сейчас, как только я прочту этот файл JSON для последующего использования, я смогу продолжать использовать его в виде списка (как против преобразования его обратно в массив).

И на самом деле выглядит лучше (на мой взгляд) на экране как список (разделенный запятыми), так и массив (не разделенный запятыми) таким образом.

Используя метод @ travelbones's .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')

Надеюсь это поможет!

1
ntk4