web-dev-qa-db-fra.com

Comment transformer une requête MongoDB en JSON?

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

Dans mon code Django/Python, je ne peux pas retourner un JSON à partir d'une requête mongo à cause de "ObjectID". L'erreur indique que "ObjectID" n'est pas sérialisable.

Que dois-je faire? Un moyen hacky serait de parcourir:

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

Le module json ne fonctionnera pas en raison de choses comme l'ObjectID.

Heureusement PyMongo fournit json_util qui ...

... autorise [s] l'encodage et le décodage spécialisés des documents BSON en mode Strict de Mongo Extended JSON. Cela vous permet d'encoder/décoder des documents BSON en JSON même lorsqu'ils utilisent des types BSON spéciaux.

29
Justin Jenkins

Voici un exemple simple, utilisant 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)
24
kelsmj

Il est assez facile d'écrire un sérialiseur personnalisé qui gère les ObjectIds. Django en inclut déjà un qui gère les décimales et les dates, vous pouvez donc étendre cela:

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)

Maintenant, vous pouvez simplement dire à json d'utiliser votre sérialiseur personnalisé:

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

Quelque chose de plus simple qui fonctionne pour moi sur Python 3.6 en utilisant le moteur == 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.
5
syberkitten