2012-07-19 19 views
25

Tôi nhận thấy vấn đề này khi máy tính chạy Ubuntu được cập nhật gần đây và phiên bản mặc định của Python đã thay đổi thành 2.7.Tại sao json.dumps (danh sách (np.arange (5))) thất bại trong khi json.dumps (np.arange (5) .tolist()) hoạt động

import json 
import numpy as np 

json.dumps(list(np.arange(5))) # Fails, throws a "TypeError: 0 is not JSON serializable" 
json.dumps(np.arange(5).tolist()) # Works 

Có sự khác biệt nào giữa danh sách() và hàm lượng tolist() của một mảng không?

+1

Tôi thấy một vấn đề tương tự, ở đây tôi không thể 'json.dumps()' biến np.int64. Tuy nhiên, nó làm việc cho tôi trong Python 2.7.9 nhưng không phải trong 3.4. –

Trả lời

23

Dường như phương pháp tolist() biến số int32 (hoặc bất kỳ kích thước nào bạn có) trở lại thành int, mà JSON biết phải làm gì với:

>>> list(np.arange(5)) 
[0, 1, 2, 3, 4] 
>>> type(list(np.arange(5))) 
<type 'list'> 
>>> type(list(np.arange(5))[0]) 
<type 'numpy.int32'> 
>>> np.arange(5).tolist() 
[0, 1, 2, 3, 4] 
>>> type(np.arange(5).tolist()) 
<type 'list'> 
>>> type(np.arange(5).tolist()[0]) 
<type 'int'> 

Như các tài liệu nói cho tolist():

Return mảng như một danh sách (có thể lồng nhau).

Trả về bản sao của dữ liệu mảng dưới dạng danh sách Python (lồng nhau). Các mục dữ liệu được chuyển đổi sang loại Python tương thích gần nhất.

Dòng cuối cùng tạo sự khác biệt ở đây.

+0

Bạn có biết đây có phải là sự thay đổi gần đây không? Mã được sử dụng để hoạt động trước khi hệ thống được nâng cấp. – azeey

+0

Không chắc chắn, tôi sợ-- thậm chí không chắc chắn liệu thay đổi này có bị thay đổi hay không (nói cách đổi tên) hoặc trên mặt JSON JSON (có thể nó đã cố gắng xử lý các loại không xác định?) – DSM

+0

[Giải pháp đơn giản] (http://stackoverflow.com/questions/8230315/python-sets-are-not-json-serializable) bằng cách chuyển một cách rõ ràng [trình xử lý mặc định] (http://docs.python.org/2/library/json. html # json.dumps) cho các đối tượng không thể tuần tự hóa. –

24

Bởi vì các yếu tố của một mảng NumPy không ints mẹ đẻ, nhưng các loại riêng NumPy của:

>>> type(np.arange(5)[0]) 
<type 'numpy.int64'> 

Bạn có thể sử dụng một tùy chỉnh JSONEncoder để hỗ trợ các loại ndarray trả về bởi arange:

import numpy as np 
import json 

class NumPyArangeEncoder(json.JSONEncoder): 
    def default(self, obj): 
     if isinstance(obj, np.ndarray): 
      return obj.tolist() # or map(int, obj) 
     return json.JSONEncoder.default(self, obj) 

print(json.dumps(np.arange(5), cls=NumPyArangeEncoder)) 
1

Vấn đề là với lần đầu tiên bạn không nhận được int. Bạn nhận được một numpy.int64. Điều đó không thể được tuần tự hóa.

Các vấn đề liên quan