我正在测试将一些文件发送到Flask路线。但是,我收到错误TypeError: <FileStorage: 'test_photo.jpg' ('image/jpeg')> is not JSON serializable
。查看路径'/new-ad/write-details
,没有任何东西试图JSON序列化此字段。
video_file = open(test_helpers.get_dummy_file('test_video.mp4'), 'rb')
image_file = open(test_helpers.get_dummy_file('test_photo.jpg'), 'rb')
response = self.app.post(
'/new-ad/write-details',
buffered=True,
content_type='multipart/form-data',
data={
'location_id': db.session.query(Location).first().id,
'category_id': db.session.query(Category).first().id,
'title': 'test title',
'body': 'test body',
'add_video': (video_file, 'test_video.mp4'),
'add_images': (image_file, 'test_photo.jpg')})
assert response.status_code == 302
assert response.location.partition('?')[0] == 'http://localhost/new-ad/preview'
ad_id = response.location.partition('?')[2].partition('=')[2]
video_file.close()
image_file.close()
Traceback (most recent call last):
File "tests.py", line 144, in test_ads_creation_routes
'add_images': (image_file, 'test_photo.jpg')})
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/werkzeug/test.py", line 801, in post
return self.open(*args, **kw)
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/flask/testing.py", line 127, in open
follow_redirects=follow_redirects)
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/werkzeug/test.py", line 764, in open
response = self.run_wsgi_app(environ, buffered=buffered)
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/werkzeug/test.py", line 677, in run_wsgi_app
rv = run_wsgi_app(self.application, environ, buffered=buffered)
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/werkzeug/test.py", line 884, in run_wsgi_app
app_rv = app(environ, start_response)
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/flask/app.py", line 1997, in __call__
return self.wsgi_app(environ, start_response)
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/flask/app.py", line 1615, in full_dispatch_request
return self.finalize_request(rv)
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/flask/app.py", line 1632, in finalize_request
response = self.process_response(response)
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/flask/app.py", line 1858, in process_response
self.save_session(ctx.session, response)
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/flask/app.py", line 924, in save_session
return self.session_interface.save_session(self, session, response)
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/flask/sessions.py", line 363, in save_session
val = self.get_signing_serializer(app).dumps(dict(session))
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/itsdangerous.py", line 565, in dumps
payload = want_bytes(self.dump_payload(obj))
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/itsdangerous.py", line 847, in dump_payload
json = super(URLSafeSerializerMixin, self).dump_payload(obj)
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/itsdangerous.py", line 550, in dump_payload
return want_bytes(self.serializer.dumps(obj))
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/flask/sessions.py", line 85, in dumps
return json.dumps(_tag(value), separators=(',', ':'))
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/flask/json.py", line 123, in dumps
rv = _json.dumps(obj, **kwargs)
File "/usr/lib/python3.5/json/__init__.py", line 237, in dumps
**kw).encode(obj)
File "/usr/lib/python3.5/json/encoder.py", line 198, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/usr/lib/python3.5/json/encoder.py", line 256, in iterencode
return _iterencode(o, 0)
File "/home/dev/Projects/ggp/lib/python3.5/site-packages/flask/json.py", line 80, in default
return _json.JSONEncoder.default(self, o)
File "/usr/lib/python3.5/json/encoder.py", line 179, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <FileStorage: 'test_photo.jpg' ('image/jpeg')> is not JSON serializable
答案 0 :(得分:1)
您展示的代码有效,与您所显示的错误无关。该错误表示您正在尝试将文件对象添加到session
。这是一个坏主意。
会话是一个cookie,它不仅大小有限,而且随着客户端发出的每个请求被发送到服务器。向其添加整个文件会无缘无故地大大增加网络流量。
如果您确实需要会话中的文件或任何JSON响应,请在磁盘上添加对其路径的引用,而不是数据本身。然后,当您需要文件发出请求单独提供文件时。 Web服务器非常擅长提供文件。
return jsonify({'video': '/path/to/video.mp4'})
如果出于某种原因,您确实需要将文件数据添加到JSON有效负载(但实际上,您不是),请先使用base64对其进行序列化。这在空间和时间上效率低下,因此将其视为最后的手段。
from base64 import b64encode
return jsonify({'video': b64encode(video.read())})
答案 1 :(得分:0)
如果没有您的测试代码,这很容易重现。
f = open('{path_to_file}', 'rb')
print(type(f))
import json
json.dumps(f)
json.dumps
将抛出异常,因为文件对象本身并不是JSON可序列化的。
Flask正在尝试在发送内容之前序列化内容,并且失败。如果要将文件内容发送到服务器,则需要读入内容并发送字节。
with open('{path_to_file}', 'rb') as f:
contents = f.read()