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


247

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

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

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


19
어딘가에 json모듈을 사용하여 numpy 배열을 덤프하려고 합니다. 그러나 처리 방법을 아는 numpy.ndarray유형은 아닙니다 json. 자신의 시리얼 라이저 list(your_array)를 작성하거나 json을 작성하는 모든 것에 전달해야 합니다.
mgilson

24
참고 list(your_array)가 NumPy와의 int가 아닌 고유의 int를 반환으로 항상 작동하지 않습니다. your_array.to_list()대신 사용하십시오 .
ashishsingal

18
@ashishsingal의 의견에 대한 메모는 to_list ()가 아니라 your_array.tolist () 여야합니다.
vega

답변:


289

나는 정기적으로 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)

3
왜 목록 목록으로 만 저장할 수 있습니까?
Nikhil Prabhu

모르겠지만 np.array 유형에는 json에 맞지 않는 메타 데이터가있을 것으로 예상됩니다 (예 : 부동 소수점과 같은 각 항목의 데이터 유형을 지정합니다)
travelingbones

2
귀하의 방법을 시도했지만 프로그램이에 붙어있는 것 같습니다 tolist().
Harvett

3
@frankliuao 나는 그 이유가 tolist()데이터가 클 때 많은 시간 이 걸린다 는 것을 알았습니다 .
Harvett

4
@NikhilPrabhu JSON은 Javascript 객체 표기법이므로 자바 스크립트 언어의 기본 구문 만 나타낼 수 있습니다 : 객체 (파이썬 딕트와 유사), 배열 (파이썬 목록과 유사), 숫자, 부울, 문자열 및 null (파이썬과 유사) 없음 ). Numpy 배열은 그러한 것이 아니므로 JSON으로 직렬화 할 수 없습니다. 일부는 JSO와 유사한 형식 (목록 목록)으로 변환 될 수 있으며이 답변이 수행하는 작업입니다.
Chris L. Barnes

225

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)

26
이것은 보드보다 훨씬 높아야하며, 일반적이고 적절하게 추상화 된 방법입니다. 감사!
thclark

2
목록에서 ndarray를 다시 가져 오는 간단한 방법이 있습니까?
DarksteelPenguin

5
찾고있는 @DarksteelPenguin 님이 numpy.asarray()아닌가요?
aeolus

3
이 답변은 훌륭하고 numpy float32 및 np.float64 값을 json으로 직렬화하도록 쉽게 확장 할 수 있습니다.if isinstance(obj, np.float32) or isinstance(obj, np.float64): return float(obj)
Bensge

이 솔루션은 모든 numpy 배열을 수동으로 캐스트하여 나열하지 않도록합니다.
eduardosufan

44

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

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

6
큰! 그리고 나는 2D np.array와 같은 것이라고 생각합니다 pd.DataFrame(your_array).to_json('data.json', orient='split').
nix

2
하루를 구했습니다. 감사합니다
anurag

40

사전에 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 파일에 속성을 작성했지만 이제 Logistic Regression의 매개 변수를 읽는 데 문제가 있습니다. 이 저장된 json 파일에 대한 '디코더'가 있습니까?
TTZ

물론 json다시 읽으려면 이것을 사용하면 with open(path, 'r') as f: data = json.load(f)데이터가있는 사전을 반환합니다.
tsveti_iko

json파일 을 읽고 출력을 역 직렬화하기 위해 다음을 사용할 수 있습니다.data = json.loads(data)
tsveti_iko

모든 바이트가 utf-8 문자열이라고 가정하고 바이트 데이터 유형을 처리하기 위해 이것을 추가해야했습니다. ELIF isinstance (OBJ (바이트)) : 리턴 obj.decode ( "UTF-8")
쇼이치 하야시

+1. "def default (self, obj)"끝에 "return json.JSONEncoder.default (self, obj)"줄이 왜 필요한가요?
Hans

23

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)

라인의 역할은 무엇입니까 type(obj).__module__ == np.__name__: ? 인스턴스를 확인하는 것으로 충분하지 않습니까?
라몬 마르티네즈

@RamonMartinez, 객체가 numpy 객체임을 알기 .item위해 거의 모든 numpy 객체에 사용할 수 있습니다 . default알 수없는 모든 유형의 json.dumps직렬화 시도에 대해 함수가 호출됩니다 . 뿐만 아니라 numpy
moshevi

5

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

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

3

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

default예를 들어 인수를 사용할 수도 있습니다 .

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

json.dump(data, default=myconverter)

1

또한 파이썬의 목록 대 배열에 대한 흥미로운 정보가 있습니다 ~> Python List vs. Array-언제 사용합니까?

JSON 파일에 저장하기 전에 배열을 목록으로 변환하고 나면 지금 배치에서 나중에 해당 JSON 파일을 나중에 읽은 후에는 목록 형식으로 계속 사용할 수 있습니다. 다시 배열로 변환하는 것과 반대입니다).

AND는 실제로 화면에서 목록 (쉼표로 구분) 대 배열 (쉼표로 구분되지 않음) 로이 방법으로 더 멋지게 보입니다.

위의 @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')

도움이 되었기를 바랍니다!


1

다음은 나를 위해 작동하고 모든 nan을 제거하는 구현입니다 (이것이 간단한 객체라고 가정 (목록 또는 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

이것은 다른 대답이지만 데이터를 저장 한 다음 다시 읽으려고하는 사람들에게 도움이 될 수 있습니다.
피클보다 빠르고 더 쉬운 방해가 있습니다.
나는 피클 덤프로 저장하고 읽으려고했지만 읽는 동안 많은 문제가 있었고 한 시간을 낭비했지만 채팅 봇을 만들기 위해 내 자신의 데이터를 작업하고 있지만 해결책을 찾지 못했습니다.

vec_xvec_yNumPy와 배열은 다음과 같습니다 :

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

그런 다음 그냥 읽고 작업을 수행하십시오.

data2 = hkl.load( 'new_data_file.hkl' )

1

검사 유형으로 간단한 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()

1

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)

0

TypeError : array ([[0.46872085, 0.67374235, 1.0218339, 0.13210179, 0.5440686, 0.9140083, 0.58720225, 0.2199381]], dtype = float32)는 JSON 직렬화 가능하지 않습니다

json 형식의 응답을 기대할 때 model.predict ()에 데이터 목록을 전달하려고 할 때 위에서 언급 한 오류가 발생했습니다.

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

그러나 운 좋게도 던지는 오류를 해결하는 힌트를 찾았습니다. 객체의 직렬화는 다음 변환에만 적용 가능합니다.

이 코드 줄이 array datatype 유형의 출력을 생성하는 행 번호 10 prediction = loaded_model.predict (d)를 보려면 위로 스크롤하면 배열을 json 형식으로 변환하려고 할 때 불가능합니다.

마지막으로 코드 행을 따라 얻은 출력을 유형 목록으로 변환하여 해결책을 찾았습니다.

예측 = loaded_model.predict (d)
목록 유형 = prediction.tolist () 반환 jsonify (listtype)

hoo! 마침내 예상되는 결과를 얻었습니다. 여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.