PyMongo
Conversion entre BSON et JSON
Recherche…
Introduction
Dans de nombreuses applications, les enregistrements de MongoDB doivent être sérialisés au format JSON. Si vos enregistrements ont des champs de type date, datetime, objectId, binary, code, etc., vous rencontrez TypeError: not JSON serializable
exceptions TypeError: not JSON serializable
lors de l'utilisation de json.dumps
. Cette rubrique montre comment surmonter cela.
Utiliser json_util
json_util fournit deux méthodes d'assistance, des dumps
et des loads
, qui encapsulent les méthodes json natives et fournissent une conversion BSON explicite vers et depuis json.
Usage simple
from bson.json_util import loads, dumps
record = db.movies.find_one()
json_str = dumps(record)
record2 = loads(json_str)
si record
est:
{
"_id" : ObjectId("5692a15524de1e0ce2dfcfa3"),
"title" : "Toy Story 4",
"released" : ISODate("2010-06-18T04:00:00Z")
}
alors json_str
devient:
{
"_id": {"$oid": "5692a15524de1e0ce2dfcfa3"},
"title" : "Toy Story 4",
"released": {"$date": 1276833600000}
}
JSONOptions
Il est possible de personnaliser le comportement des dumps
au moyen d' un JSONOptions
objet. Deux ensembles d'options sont déjà disponibles: DEFAULT_JSON_OPTIONS
et STRICT_JSON_OPTIONS
.
>>> bson.json_util.DEFAULT_JSON_OPTIONS
JSONOptions(strict_number_long=False, datetime_representation=0,
strict_uuid=False, document_class=dict, tz_aware=True,
uuid_representation=PYTHON_LEGACY, unicode_decode_error_handler='strict',
tzinfo=<bson.tz_util.FixedOffset object at 0x7fc168a773d0>)
Pour utiliser différentes options, vous pouvez:
modifiez l'objet
DEFAULT_JSON_OPTIONS
. Dans ce cas, les options seront utilisées pour tous les appels suivants auxdumps
:from bson.json_util import DEFAULT_JSON_OPTIONS DEFAULT_JSON_OPTIONS.datetime_representation = 2 dumps(record)
spécifier un
JSONOptions
dans un appel àdumps
utilisant le paramètrejson_options
:# using strict dumps(record, json_options=bson.json_util.STRICT_JSON_OPTIONS) # using a custom set of options from bson.json_util import JSONOptions options = JSONOptions() # options is a copy of DEFAULT_JSON_OPTIONS options.datetime_representation=2 dumps(record, json_options=options)
Les paramètres de JSONOptions
sont les suivants:
- strict_number_long : Si true, les objets Int64 sont codés dans le type Strict NumberLong du mode Strict de MongoDB Extended JSON, c'est-à-dire
{"$numberLong": "<number>" }
. Sinon, ils seront encodés en int. La valeur par défaut est False. - datetime_representation : représentation à utiliser lors du codage des instances de datetime.datetime. 0 =>
{"$date": <dateAsMilliseconds>}
, 1 =>{"$date": {"$numberLong": "<dateAsMilliseconds>"}}
, 2 =>{"$date": "<ISO-8601>"}
- strict_uuid : Si true, l'objet uuid.UUID est codé dans le type de mode Strict Binary de MongoDB Extended JSON. Sinon, il sera codé comme
{"$uuid": "<hex>" }
. La valeur par défaut est False. - document_class : Les documents BSON renvoyés par load () seront décodés en une instance de cette classe. Doit être une sous-classe de collections.MutableMapping. Par défaut, dict.
- uuid_representation : représentation BSON à utiliser lors du codage et du décodage des instances de uuid.UUID. La valeur par défaut est PYTHON_LEGACY.
- tz_aware : Si la valeur est true, le type de mode Strict de MongoDB Extended JSON Date sera décodé en instances de datetime.datetime identifiées par le fuseau horaire. Sinon, ils seront naïfs. La valeur par défaut est True.
- tzinfo : Une sous-classe
datetime.tzinfo
qui spécifie le fuseau horaire à partir duquel les objets datetime doivent être décodés. La valeur par défaut est utc.
Utiliser python-bsonjs
python-bsonjs ne dépend pas de PyMongo et peut offrir une amélioration des performances par rapport à json_util
:
bsonjs est environ 10 à 15 fois plus rapide que json_util de PyMongo pour décoder BSON en JSON et encoder JSON en BSON.
Notez que:
- pour utiliser efficacement bsonjs, il est recommandé de travailler directement avec
RawBSONDocument
- les dates sont codées en utilisant la représentation LEGACY, c'est-à-dire
{"$date": <dateAsMilliseconds>}
. Il n'y a actuellement aucune option pour changer cela.
Installation
pip install python-bsonjs
Usage
Pour tirer pleinement parti des bsonjs, configurez la base de données pour utiliser la classe RawBSONDocument
. Ensuite, utilisez dumps
pour convertir des octets bruts bson en json et des loads
pour convertir json en octets bruts bson:
import pymongo
import bsonjs
from pymongo import MongoClient
from bson.raw_bson import RawBSONDocument
# configure mongo to use the RawBSONDocument representation
db = pymongo.MongoClient(document_class=RawBSONDocument).samples
# convert json to a bson record
json_record = '{"_id": "some id", "title": "Awesome Movie"}'
raw_bson = bsonjs.loads(json_record)
bson_record = RawBSONDocument(raw_bson)
# insert the record
result = db.movies.insert_one(bson_record)
print(result.acknowledged)
# find some record
bson_record2 = db.movies.find_one()
# convert the record to json
json_record2 = bsonjs.dumps(bson_record2.raw)
print(json_record2)
Utilisation du module json avec des gestionnaires personnalisés
Si tout ce dont vous avez besoin est la sérialisation des résultats de mongo dans json, il est possible d'utiliser le module json
, à condition que vous définissiez des gestionnaires personnalisés pour gérer les types de champs non sérialisables. Un avantage est que vous disposez de toute la puissance nécessaire pour encoder des champs spécifiques, tels que la représentation datetime.
Voici un gestionnaire qui code les dates en utilisant la représentation iso et l'ID sous forme de chaîne hexadécimale:
import pymongo
import json
import datetime
import bson.objectid
def my_handler(x):
if isinstance(x, datetime.datetime):
return x.isoformat()
elif isinstance(x, bson.objectid.ObjectId):
return str(x)
else:
raise TypeError(x)
db = pymongo.MongoClient().samples
record = db.movies.find_one()
# {u'_id': ObjectId('5692a15524de1e0ce2dfcfa3'), u'title': u'Toy Story 4',
# u'released': datetime.datetime(2010, 6, 18, 4, 0),}
json_record = json.dumps(record, default=my_handler)
# '{"_id": "5692a15524de1e0ce2dfcfa3", "title": "Toy Story 4",
# "released": "2010-06-18T04:00:00"}'