折腾:
期间,用代码:
<code>import os
from datetime import datetime
from flask import jsonify
from flask_restful import Resource
from flask_restful import reqparse
from bson.objectid import ObjectId
from common.FlaskLogSingleton import log
from flask import g
bookCollection = g.mongoCollection
from conf.app import settings
class xxxAPI(Resource):
def get(self, bookId=None):
log.info("bookId=%s, ", bookId)
respDict = {
"code": 200,
"message": "ok",
"data": {}
}
if not bookId:
respDict = {
"code": 404,
"message": "Book Id can not be empty",
"data": {}
}
log.info("respDict=%s", respDict)
return jsonify(respDict)
bookIdObj = ObjectId(bookId)
log.info("bookIdObj=%s", bookIdObj)
bookObj = bookCollection.find_one({'_id': bookIdObj})
log.info("bookObj=%s", bookObj)
if not bookObj:
respDict = {
"code": 404,
"message": "Can not find book from object id %s" % (bookId),
"data": {}
}
return jsonify(respDict)
respDict["data"] = bookIdObj
return jsonify(respDict)
def create_rest_api(app):
from resources.storybook import xxxAPI
rest_api = Api()
rest_api.add_resource(xxxAPI, '/storybook/<bookId>', endpoint='storybook')
rest_api.init_app(app)
return rest_api
</code>然后本地调试访问url:
http://localhost:33800/storybook/5bc5e57bbfaa4425b7ea324a
结果报错:
<code>Traceback (most recent call last): File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask/app.py", line 2309, in __call__ return self.wsgi_app(environ, start_response) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask/app.py", line 2295, in wsgi_app response = self.handle_exception(e) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask_restful/__init__.py", line 273, in error_router return original_handler(e) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask_cors/extension.py", line 161, in wrapped_function return cors_after_request(app.make_response(f(*args, **kwargs))) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask/app.py", line 1741, in handle_exception reraise(exc_type, exc_value, tb) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask/_compat.py", line 34, in reraise raise value.with_traceback(tb) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app response = self.full_dispatch_request() File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request rv = self.handle_user_exception(e) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask_restful/__init__.py", line 273, in error_router return original_handler(e) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask_cors/extension.py", line 161, in wrapped_function return cors_after_request(app.make_response(f(*args, **kwargs))) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception reraise(exc_type, exc_value, tb) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask/_compat.py", line 34, in reraise raise value.with_traceback(tb) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request rv = self.dispatch_request() File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request return self.view_functions[rule.endpoint](**req.view_args) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask_restful/__init__.py", line 480, in wrapper resp = resource(*args, **kwargs) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask/views.py", line 88, in view return self.dispatch_request(*args, **kwargs) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask_restful/__init__.py", line 595, in dispatch_request resp = meth(*args, **kwargs) File "/Users/crifan/dev/dev_root/company/naturling/projects/xxx/server/xxx/resources/storybook.py", line 48, in get return jsonify(respDict) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask/json/__init__.py", line 321, in jsonify dumps(data, indent=indent, separators=separators) + '\n', File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask/json/__init__.py", line 179, in dumps rv = _json.dumps(obj, **kwargs) File "/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/__init__.py", line 238, in dumps **kw).encode(obj) File "/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 201, in encode chunks = list(chunks) File "/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 430, in _iterencode yield from _iterencode_dict(o, _current_indent_level) File "/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 404, in _iterencode_dict yield from chunks File "/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 437, in _iterencode o = _default(o) File "/Users/crifan/.local/share/virtualenvs/xxx-BuV5JJj8/lib/python3.6/site-packages/flask/json/__init__.py", line 81, in default return _json.JSONEncoder.default(self, o) File "/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/lib/python3.6/json/encoder.py", line 180, in default o.__class__.__name__) TypeError: Object of type 'ObjectId' is not JSON serializable </code>
flask pymongo TypeError: Object of type ‘ObjectId’ is not JSON serializable
python – TypeError: ObjectId(”) is not JSON serializable – Stack Overflow
道理上应该用Pymongo的 json_util
但是发现被人提到的这个方式更好:
去掉_id属性,然后此处自己再加上_id: idStr,更好
<code># respDict["data"] = bookObj
# -> TypeError: Object of type 'ObjectId' is not JSON serializable
bookDict = bookObj
bookDict.pop("_id")
bookDict["id"] = bookId
respDict["data"] = bookDict
return jsonify(respDict)
</code>调试看到返回之前的dict值:

就可以正常返回json了:

换用Chrome中JsonHandler,效果更清楚:

【总结】
此处pymongo的collection返回的单个值,是个dict,但是其中包含了特殊的:
“_id” : ObjectId(“xxx”)
导致此处Flask中用:
return jsonify(respDict)
会报错:
TypeError: Object of type ‘ObjectId’ is not JSON serializable
正常的解决办法:
使用PyMongo的json_util
http://api.mongodb.com/python/current/api/bson/json_util.html
就支持ObjectId了
此处的办法:
由于返回给用户,也不希望用到_id,只需要id,所以做法是:
去掉_id
加上id
代码:
<code># respDict["data"] = bookObj
# -> TypeError: Object of type 'ObjectId' is not JSON serializable
bookDict = bookObj
bookDict.pop("_id")
bookDict["id"] = bookId
respDict["data"] = bookDict
return jsonify(respDict)
</code>即可。
转载请注明:在路上 » 【已解决】Flask中返回MongoDB的collection对象出错:TypeError: Object of type ‘ObjectId’ is not JSON serializable