首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >TypeError: ObjectId('')不可序列化

TypeError: ObjectId('')不可序列化
EN

Stack Overflow用户
提问于 2013-05-16 19:25:18
回答 13查看 144.1K关注 0票数 133

我从MongoDB返回的响应在使用Python查询文档上的聚合函数后,它返回有效的响应,我可以打印它,但不能返回它。

错误:

代码语言:javascript
复制
TypeError: ObjectId('51948e86c25f4b1d1c0d303c') is not JSON serializable

打印:

代码语言:javascript
复制
{'result': [{'_id': ObjectId('51948e86c25f4b1d1c0d303c'), 'api_calls_with_key': 4, 'api_calls_per_day': 0.375, 'api_calls_total': 6, 'api_calls_without_key': 2}], 'ok': 1.0}

但当我试着返回时:

代码语言:javascript
复制
TypeError: ObjectId('51948e86c25f4b1d1c0d303c') is not JSON serializable

这是RESTfull调用:

代码语言:javascript
复制
@appv1.route('/v1/analytics')
def get_api_analytics():
    # get handle to collections in MongoDB
    statistics = sldb.statistics

    objectid = ObjectId("51948e86c25f4b1d1c0d303c")

    analytics = statistics.aggregate([
    {'$match': {'owner': objectid}},
    {'$project': {'owner': "$owner",
    'api_calls_with_key': {'$cond': [{'$eq': ["$apikey", None]}, 0, 1]},
    'api_calls_without_key': {'$cond': [{'$ne': ["$apikey", None]}, 0, 1]}
    }},
    {'$group': {'_id': "$owner",
    'api_calls_with_key': {'$sum': "$api_calls_with_key"},
    'api_calls_without_key': {'$sum': "$api_calls_without_key"}
    }},
    {'$project': {'api_calls_with_key': "$api_calls_with_key",
    'api_calls_without_key': "$api_calls_without_key",
    'api_calls_total': {'$add': ["$api_calls_with_key", "$api_calls_without_key"]},
    'api_calls_per_day': {'$divide': [{'$add': ["$api_calls_with_key", "$api_calls_without_key"]}, {'$dayOfMonth': datetime.now()}]},
    }}
    ])


    print(analytics)

    return analytics

db连接良好,集合也在那里,我得到了有效的预期结果,但当我尝试返回时,它给出了Json错误。是否知道如何将响应转换回JSON。谢谢

EN

回答 13

Stack Overflow用户

回答已采纳

发布于 2013-05-16 19:30:55

你应该定义你自己的JSONEncoder并使用它:

代码语言:javascript
复制
import json
from bson import ObjectId

class JSONEncoder(json.JSONEncoder):
    def default(self, o):
        if isinstance(o, ObjectId):
            return str(o)
        return json.JSONEncoder.default(self, o)

JSONEncoder().encode(analytics)

也可以通过以下方式使用它。

代码语言:javascript
复制
json.encode(analytics, cls=JSONEncoder)
票数 147
EN

Stack Overflow用户

发布于 2013-08-23 22:41:55

Pymongo提供了json_util -您可以使用它来处理BSON类型

代码语言:javascript
复制
def parse_json(data):
    return json.loads(json_util.dumps(data))
票数 164
EN

Stack Overflow用户

发布于 2014-11-20 02:38:25

代码语言:javascript
复制
>>> from bson import Binary, Code
>>> from bson.json_util import dumps
>>> dumps([{'foo': [1, 2]},
...        {'bar': {'hello': 'world'}},
...        {'code': Code("function x() { return 1; }")},
...        {'bin': Binary("")}])
'[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }", "$scope": {}}}, {"bin": {"$binary": "AQIDBA==", "$type": "00"}}]'

来自json_util的实际示例。

与Flask的jsonify不同,“dump”将返回一个字符串,因此它不能用作Flask的jsonify的1:1替换。

this question表明,我们可以使用json_util.dumps()进行序列化,使用json.loads()转换回dict,最后对其调用Flask的jsonify。

示例(源自上一个问题的答案):

代码语言:javascript
复制
from bson import json_util, ObjectId
import json

#Lets create some dummy document to prove it will work
page = {'foo': ObjectId(), 'bar': [ObjectId(), ObjectId()]}

#Dump loaded BSON to valid JSON string and reload it as dict
page_sanitized = json.loads(json_util.dumps(page))
return page_sanitized

此解决方案将ObjectId和其他(即二进制、代码等)转换为字符串等效项,如“$oid”。

JSON输出将如下所示:

代码语言:javascript
复制
{
  "_id": {
    "$oid": "abc123"
  }
}
票数 48
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16586180

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档