Ответ 1
Похоже, ты прав:
>>> import numpy
>>> import json
>>> json.dumps(numpy.int32(685))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/json/__init__.py", line 243, in dumps
return _default_encoder.encode(obj)
File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
return _iterencode(o, 0)
File "/usr/lib/python2.7/json/encoder.py", line 184, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: 685 is not JSON serializable
К сожалению, здесь то, что числовые числа __repr__
не дают вам никаких намеков на их тип. Они бегают, маскируясь под int
когда нет (задыхаются). В конечном счете, похоже, что json
говорит вам, что int
не сериализуем, но на самом деле он говорит вам, что этот конкретный np.int32 (или любой другой тип, который у вас есть) не сериализуем. (Никакого реального сюрприза там нет - np.int32 не сериализуем). По этой же причине изречение, которое вы неизбежно напечатали перед передачей его в json.dumps
выглядит так, будто в нем тоже есть целые числа.
Самый простой обходной путь - написать собственный сериализатор 1:
class MyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, numpy.integer):
return int(obj)
elif isinstance(obj, numpy.floating):
return float(obj)
elif isinstance(obj, numpy.ndarray):
return obj.tolist()
else:
return super(MyEncoder, self).default(obj)
Вы используете это так:
json.dumps(numpy.float32(1.2), cls=MyEncoder)
json.dumps(numpy.arange(12), cls=MyEncoder)
json.dumps({'a': numpy.int32(42)}, cls=MyEncoder)
и т.п.
1 Или вы можете просто написать функцию по умолчанию и передать ее в качестве defaut
ключевого слова json.dumps
в json.dumps
.В этом случае вы бы заменили последнюю строку на raise TypeError
, но... ме.Класс более расширяемый :-)