2010-12-10 32 views
29
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 renvoyer un JSON d'une requête mongo à cause de "ObjectID". L'erreur indique que "ObjectID" n'est pas sérialisable.Comment transformer la requête MongoDB en JSON?

Que dois-je faire? Une façon hacky serait en boucle par:

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

Répondre

27

Le Module JSON ne fonctionnera pas en raison de choses comme ObjectId.

Heureusement PyMongo fournit json_util qui ...

... permettent [s] pour le codage spécialisé et décodage des documents BSON en mode Mongo Strict Extended JSON. Cela permet vous coder/décoder les documents BSON à JSON même lorsqu'ils utilisent des types spéciaux BSON .

Plus ici: http://api.mongodb.org/python/1.9%2B/api/bson/json_util.html#module-bson.json_util

+0

Comment l'importer? – TIMEX

+0

http://api.mongodb.org/python/1.9%2B/installation.html & http://api.mongodb.org/python/1.9%2B/tutorial.html & >>> import pymongo –

+1

Réponse complète ici : http://stackoverflow.com/a/27024423/1731454 – oferei

8

Il est assez facile d'écrire un sérialiseur personnalisé qui se débrouille avec les ObjectIds. Django comprend déjà un qui gère les décimales et les dates, vous pouvez donc étendre que:

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 utiliser votre sérialiseur personnalisé:

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

Vous avez besoin de 'import bson' pour que cela fonctionne (je le mentionne simplement parce que je suis un newb et cela m'a pris du temps) – ario

20

Voici un exemple simple, en 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) 
+0

json.dumps (doc, sort_keys = True, indent = 4, default = json_util. par défaut) a résolu mon problème aussi! –

+3

quelle est la différence avec l'utilisation de 'json_util.dumps (doc)'? – njzk2

+0

Vous devriez aussi importer 'json' pour que ce code fonctionne, n'est-ce pas? – Leukonoe

2

Quelque chose encore plus simple qui fonctionne pour moi sur Python 3.6 en utilisant 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.