¿Cómo convierto la consulta de MongoDB en un JSON?

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

En mi código Django / Python, no puedo devolver un JSON desde una consulta de Mongo debido a “ObjectID”. El error dice que “ObjectID” no es serializable.

¿Que tengo que hacer? Una forma de pirateo sería atravesar:

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

El módulo json no funcionará debido a cosas como el ObjectID.

Afortunadamente PyMongo proporciona json_util que …

… permite [s] para la encoding y deencoding especializada de documentos BSON en el modo estricto de Mongo Extended JSON. Esto le permite codificar / decodificar documentos BSON a JSON incluso cuando utilizan tipos BSON especiales.

Aquí hay una muestra simple, usando 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) 

Es bastante fácil escribir un serializador personalizado que haga frente a los ObjectIds. Django ya incluye uno que maneja decimales y fechas, por lo que puede extender eso:

 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) 

Ahora puede decirle a json que use su serializador personalizado:

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

Algo aún más simple que me funciona en Python 3.6 usando motor == 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  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  into a  back_to_dict = loads(json_string) # to unserialize, thus return the string back to a  with the original 'ObjectID' type.