[python] NumPy 배열은 JSON 직렬화 가능하지 않습니다

NumPy 배열을 만들고 장고 컨텍스트 변수로 저장 한 후 웹 페이지를로드 할 때 다음 오류가 발생합니다.

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

이것은 무엇을 의미 하는가?



답변

나는 정기적으로 np.arrays를 “jsonify”합니다. 먼저 다음과 같이 배열에서 “.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)


답변

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)


답변

팬더 를 사용할 수 있습니다 :

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


답변

사전에 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)

이 사람 에게 감사합니다 .


답변

json.dumps defaultkwarg를 사용하십시오 .

default는 달리 직렬화 할 수없는 객체에 대해 호출되는 함수 여야합니다.

에서 default기능 검사 대상물이 모듈에서 NumPy와이면 어느 용도 그렇다면 ndarray.tolistA에 대한 ndarray사용하거나 .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)


답변

이 기능은 기본적으로 지원되지 않지만 매우 쉽게 작동 할 수 있습니다! 똑같은 데이터를 다시 원한다면 인코딩하고 싶은 것이 몇 가지 있습니다.

  • obj.tolist()@travelingbones가 언급 한대로 얻을 수있는 데이터 자체 . 때로는 이것으로 충분할 수 있습니다.
  • 데이터 타입. 나는 이것이 매우 중요한 경우라고 생각합니다.
  • 입력이 항상 ‘직사각형’그리드라고 가정하면 위로부터 파생 될 수있는 치수 (2D 일 필요는 없음)입니다.
  • 메모리 순서 (행 또는 열 주요). 이것은 종종 중요하지 않지만 때로는 중요합니다 (예 : 성능). 왜 모든 것을 저장하지 않습니까?

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


답변

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