Ma réponse de MongoDB après avoir interrogé une fonction agrégée sur un document en utilisant Python, elle renvoie une réponse valide et je peux l'imprimer mais je ne peux pas la renvoyer.
Erreur:
TypeError: ObjectId('51948e86c25f4b1d1c0d303c') is not JSON serializable
Impression:
{'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}
Mais quand j'essaye de revenir:
TypeError: ObjectId('51948e86c25f4b1d1c0d303c') is not JSON serializable
C'est l'appel RESTfull:
@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 est bien connecté et la collection est là aussi et j'ai récupéré un résultat attendu valide, mais lorsque j'essaye de retourner, cela me donne une erreur Json. Toute idée de la façon de reconvertir la réponse en JSON. Merci
if isinstance(o, ObjectId): return str(o)
avantreturn
dans la méthodedefault
.from bson import ObjectId
, pour que tout le monde puisse copier-coller encore plus rapidement? Merci!str
? Quel est le problème avec cette approche?Pymongo fournit json_util - vous pouvez utiliser celui-ci à la place pour gérer les types BSON
la source
from bson import json_util
json.loads(json_util.dumps(user_collection))
^ cela a fonctionné après l'installation de python-bsonjs avecpipenv install python-bsonjs
Exemple réel de json_util .
Contrairement à jsonify de Flask, "dumps" renverra une chaîne, donc il ne peut pas être utilisé comme un remplacement 1: 1 du jsonify de Flask.
Mais cette question montre que nous pouvons sérialiser en utilisant json_util.dumps (), reconvertir en dict en utilisant json.loads () et enfin appeler le jsonify de Flask dessus.
Exemple (dérivé de la réponse à la question précédente):
Cette solution convertira ObjectId et d'autres (c'est-à-dire Binaire, Code, etc.) en une chaîne équivalente telle que "$ oid".
La sortie JSON ressemblerait à ceci:
la source
La plupart des utilisateurs qui reçoivent l'erreur "non sérialisable JSON" doivent simplement le spécifier
default=str
lors de l'utilisationjson.dumps
. Par exemple:Cela forcera une conversion en
str
, empêchant l'erreur. Bien sûr, regardez ensuite la sortie générée pour confirmer que c'est ce dont vous avez besoin.la source
Voici l'exemple d'exemple de conversion de BSON en objet JSON. Vous pouvez essayer ceci.
la source
En remplacement rapide, vous pouvez passer
{'owner': objectid}
à{'owner': str(objectid)}
.Mais définir la vôtre
JSONEncoder
est une meilleure solution, cela dépend de vos besoins.la source
Publier ici car je pense que cela peut être utile pour les personnes utilisant
Flask
avecpymongo
. C'est ma configuration actuelle de "meilleure pratique" pour permettre à flask de rassembler les types de données pymongo bson.mongoflask.py
app.py
Pourquoi faire cela au lieu de servir BSON ou mongod Extended JSON ?
Je pense que servir mongo special JSON met un fardeau sur les applications clientes. La plupart des applications clientes ne se soucieront pas d'utiliser des objets mongo de manière complexe. Si je sers du json étendu, je dois maintenant l'utiliser côté serveur et côté client.
ObjectId
etTimestamp
sont plus faciles à travailler en tant que chaînes et cela maintient toute cette folie de marshalling mongo en quarantaine sur le serveur.Je pense que cela est moins coûteux à utiliser pour la plupart des applications que.
la source
Voici comment j'ai récemment corrigé l'erreur
la source
Je sais que je poste en retard, mais j'ai pensé que cela aiderait au moins quelques personnes!
Les exemples mentionnés par tim et defuz (qui sont les mieux votés) fonctionnent parfaitement bien. Cependant, il existe une différence infime qui peut parfois être significative.
Pymongo fournit json_util - vous pouvez utiliser celui-ci à la place pour gérer les types BSON
Sortie: {"_id": {"$ oid": "abc123"}}
Sortie: {"_id": "abc123"}
Même si la première méthode semble simple, les deux méthodes nécessitent un effort très minime.
la source
pytest-mongodb
plugin lors de la création de luminairesdans mon cas, j'avais besoin de quelque chose comme ça:
la source
object['_id'] = str(object['_id'])
Jsonify de Flask fournit une amélioration de la sécurité comme décrit dans la sécurité JSON . Si un encodeur personnalisé est utilisé avec Flask, il est préférable de prendre en compte les points abordés dans la sécurité JSON
la source
Je souhaite apporter une solution supplémentaire qui améliore la réponse acceptée. J'ai déjà fourni les réponses dans un autre fil ici .
la source
Si vous n'avez pas besoin du _id des enregistrements, je vous recommanderai de le désactiver lors de l'interrogation de la base de données, ce qui vous permettra d'imprimer directement les enregistrements retournés, par exemple
Pour annuler le _id lors de l'interrogation, puis imprimer des données dans une boucle, vous écrivez quelque chose comme ceci
la source
SOLUTION pour: mongoengine + guimauve
Si vous utilisez
mongoengine
etmarshamallow
alors cette solution peut être applicable pour vous.Fondamentalement, j'ai importé un
String
champ de guimauve et j'ai écrasé la valeur par défautSchema id
pour êtreString
encodé.la source
la source
Si vous ne voulez pas
_id
de réponse, vous pouvez refactoriser votre code comme ceci:Cela supprimera l'
TypeError: ObjectId('') is not JSON serializable
erreur.la source