Ricerca…


introduzione

In molte applicazioni, i record di MongoDB devono essere serializzati in formato JSON. Se i tuoi record hanno campi di tipo data, datetime, objectId, binary, code, ecc. Incontrerai TypeError: not JSON serializable eccezioni TypeError: not JSON serializable quando usi json.dumps . Questo argomento mostra come superare questo.

Usando json_util

json_util fornisce due metodi helper, dumps e loads , che avvolgono i metodi json nativi e forniscono la conversione esplicita BSON da e verso json.

Uso semplice

from bson.json_util import loads, dumps
record = db.movies.find_one()
json_str = dumps(record)
record2 = loads(json_str)

se il record è:

{ 
    "_id" : ObjectId("5692a15524de1e0ce2dfcfa3"), 
    "title" : "Toy Story 4", 
    "released" : ISODate("2010-06-18T04:00:00Z") 
}

allora json_str diventa:

{
    "_id": {"$oid": "5692a15524de1e0ce2dfcfa3"},
    "title" : "Toy Story 4", 
    "released": {"$date": 1276833600000}
}

JSONOptions

È possibile personalizzare il comportamento dei dumps tramite un oggetto JSONOptions . Sono già disponibili due serie di opzioni: DEFAULT_JSON_OPTIONS e 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>) 

Per utilizzare diverse opzioni, puoi:

  1. modificare l'oggetto DEFAULT_JSON_OPTIONS . In questo caso, le opzioni verranno utilizzate per tutte le successive chiamate a dumps :

     from bson.json_util import DEFAULT_JSON_OPTIONS
     DEFAULT_JSON_OPTIONS.datetime_representation = 2
     dumps(record)
    
  2. specificare un JSONOptions in una chiamata ai dumps usando il parametro json_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)
    

I parametri di JSONOptions sono:

  • strict_number_long : Se true, gli oggetti Int64 sono codificati in MongoDB Extended JSON's Strict tipo NumberLong, ovvero {"$numberLong": "<number>" } . Altrimenti saranno codificati come int. Il valore predefinito è Falso.
  • datetime_representation : la rappresentazione da utilizzare durante la codifica delle istanze di datetime.datetime. 0 => {"$date": <dateAsMilliseconds>} , 1 => {"$date": {"$numberLong": "<dateAsMilliseconds>"}} , 2 => {"$date": "<ISO-8601>"}
  • strict_uuid : Se true, l'oggetto uuid.UUID è codificato in MongoDB Extended JSON's Strict mode binary. Altrimenti sarà codificato come {"$uuid": "<hex>" } . Il valore predefinito è Falso.
  • document_class : i documenti BSON restituiti da loads () verranno decodificati su un'istanza di questa classe. Deve essere una sottoclasse di collections.MutableMapping. Impostazioni predefinite da dettare.
  • uuid_representation : la rappresentazione BSON da utilizzare durante le istanze di codifica e decodifica di uuid.UUID. Il valore predefinito è PYTHON_LEGACY.
  • tz_aware : se true, il tipo di modalità Strict di MongoDB Extended JSON Data verrà decodificato in istanze timezone aware di datetime.datetime. Altrimenti saranno ingenui. Il valore predefinito è True.
  • tzinfo : una sottoclasse datetime.tzinfo che specifica il fuso orario dal quale devono essere decodificati gli oggetti datetime. Predefinito a utc.

Utilizzando python-bsonjs

python-bsonjs non dipende da PyMongo e può offrire un buon miglioramento delle prestazioni rispetto a json_util :

bsonjs è all'incirca 10-15 volte più veloce di json_util di PyMongo per decodificare BSON in JSON e codificare JSON in BSON.

Nota che:

  • per usare efficacemente bsonjs, si raccomanda di lavorare direttamente con RawBSONDocument
  • le date sono codificate usando la rappresentazione LEGACY, cioè {"$date": <dateAsMilliseconds>} . Al momento non ci sono opzioni per cambiarlo.

Installazione

pip install python-bsonjs

uso

Per trarre il massimo vantaggio da bsonjs, configurare il database per utilizzare la classe RawBSONDocument . Quindi, usa i dumps per convertire i byte raw di bson in json e loads per convertire i byte json in bson raw:

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)

Usare il modulo json con i gestori personalizzati

Se tutto ciò di cui hai bisogno è serializzare i risultati di mongo in json, è possibile utilizzare il modulo json , a patto di definire gestori personalizzati per gestire tipi di campi non serializzabili. Un vantaggio è che hai piena potenza su come codificare campi specifici, come la rappresentazione datetime.

Ecco un gestore che codifica le date usando la rappresentazione iso e l'id come una stringa esadecimale:

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"}'


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow