最新消息:20210917 已从crifan.com换到crifan.org

【已解决】Flask中返回MongoDB的collection对象出错:TypeError: Object of type ‘ObjectId’ is not JSON serializable

Flask crifan 6139浏览 0评论

折腾:

【已解决】Mac本地搭建用Flask绘本查询推荐系统后台

期间,用代码:

<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/&lt;bookId&gt;', 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
# -&gt; 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
# -&gt; 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

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
99 queries in 0.188 seconds, using 23.39MB memory