Подтвердить что ты не робот

Как превратить запрос MongoDB в JSON?

for p in db.collection.find({"test_set":"abc"}):
    posts.append(p)
thejson = json.dumps({'results':posts})
return  HttpResponse(thejson, mimetype="application/javascript")

В моем коде Django/Python я не могу вернуть JSON из запроса mongo из-за "ObjectID". Ошибка говорит, что "ObjectID" не является сериализуемым.

Что мне делать? Хакерным способом было бы пройти через:

for p in posts:
    p['_id'] = ""
4b9b3361

Ответ 1

Модуль json не будет работать из-за таких вещей, как ObjectID.

К счастью PyMongo предоставляет json_util, который...

... разрешить [s] для специализированного кодирования и декодирование документов BSON в Mongo Расширенный режим JSON Strict. Это позволяет вы кодируете/декодируете документы BSON для JSON, даже если они используют специальный BSON типы.

Подробнее здесь: http://api.mongodb.org/python/1.9%2B/api/bson/json_util.html#module-bson.json_util

Ответ 2

Вот простой пример, используя pymongo 2.2.1

import os
import sys
import json
import pymongo
from bson import BSON
from bson import json_util

if __name__ == '__main__':
  try:
    connection = pymongo.Connection('mongodb://localhost:27017')
    database = connection['mongotest']
  except:
    print('Error: Unable to Connect')
    connection = None

  if connection is not None:
    database["test"].insert({'name': 'foo'})
    doc = database["test"].find_one({'name': 'foo'})
    return json.dumps(doc, sort_keys=True, indent=4, default=json_util.default)

Ответ 3

Очень легко написать собственный сериализатор, который справляется с ObjectIds. Django уже включает в себя тот, который обрабатывает десятичные знаки и даты, поэтому вы можете расширить это:

from django.core.serializers.json import DjangoJSONEncoder
from bson import objectid

class MongoAwareEncoder(DjangoJSONEncoder):
    """JSON encoder class that adds support for Mongo objectids."""
    def default(self, o):
        if isinstance(o, objectid.ObjectId):
            return str(o)
        else:
            return super(MongoAwareEncoder, self).default(o)

Теперь вы можете просто сказать json использовать свой собственный сериализатор:

thejson = json.dumps({'results':posts}, cls=MongoAwareEncoder)

Ответ 4

Что-то еще более простое, что работает для меня на Python 3.6, используя двигатель == 1,1 PyMongo == 3.4.0

from bson.json_util import dumps, loads

for mongo_doc in await cursor.to_list(length=10):
    # mongo_doc is a <class 'dict'> returned from the async mongo driver, in this acse motor / pymongo.
    # result of executing a simple find() query.

    json_string = dumps(mongo_doc)
    # serialize the <class 'dict'> into a <class 'str'> 

    back_to_dict = loads(json_string)
    # to unserialize, thus return the string back to a <class 'dict'> with the original 'ObjectID' type.