Szukaj…


Wprowadzenie

W wielu aplikacjach rekordy z MongoDB muszą być serializowane w formacie JSON. Jeśli twoje rekordy zawierają pola typu data, data / godzina, objectId, plik binarny, kod itp., json.dumps TypeError: not JSON serializable wyjątków TypeError: not JSON serializable podczas używania json.dumps . Ten temat pokazuje, jak temu zaradzić.

Korzystanie z json_util

json_util zapewnia dwie metody pomocnicze, dumps i loads , które obejmują natywne metody json i zapewniają jawną konwersję BSON do i z json.

Proste użycie

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

jeśli record jest:

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

wtedy json_str staje się:

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

JSONOptions

Możliwe jest dostosowanie zachowania dumps za pomocą obiektu JSONOptions . Dostępne są już dwa zestawy opcji: DEFAULT_JSON_OPTIONS i 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>) 

Aby użyć różnych opcji, możesz:

  1. zmodyfikuj obiekt DEFAULT_JSON_OPTIONS . W takim przypadku opcje będą używane dla wszystkich kolejnych wywołań dumps :

     from bson.json_util import DEFAULT_JSON_OPTIONS
     DEFAULT_JSON_OPTIONS.datetime_representation = 2
     dumps(record)
    
  2. określ JSONOptions w wywołaniu dumps za pomocą parametru 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)
    

Parametry JSONOptions to:

  • strict_number_long : Jeśli true, obiekty Int64 są kodowane w trybie ścisłego trybu JSON w MongoDB Extended JSON typu NumberLong, tj. {"$numberLong": "<number>" } . W przeciwnym razie zostaną zakodowane jako int. Domyślnie False.
  • datetime_representation : reprezentacja używana podczas kodowania instancji datetime.datetime. 0 => {"$date": <dateAsMilliseconds>} , 1 => {"$date": {"$numberLong": "<dateAsMilliseconds>"}} , 2 => {"$date": "<ISO-8601>"}
  • strict_uuid : Jeśli true, obiekt uuid.UUID jest zakodowany w trybie ścisłym trybu MongoDB Extended JSON typu Binary. W przeciwnym razie będzie zakodowany jako {"$uuid": "<hex>" } . Domyślnie False.
  • document_class : Dokumenty BSON zwrócone przez load () zostaną zdekodowane do instancji tej klasy. Musi być podklasą kolekcji.MutableMapping. Domyślnie dyktuje.
  • uuid_representation : reprezentacja BSON używana podczas kodowania i dekodowania instancji uuid.UUID. Domyślnie PYTHON_LEGACY.
  • tz_aware : Jeśli to prawda, typ ścisłego trybu JSON Extended w MongoDB Date zostanie zdekodowany do instancji datetime.datetime rozpoznających strefę czasową. W przeciwnym razie będą naiwni. Domyślna wartość to True.
  • tzinfo : Podklasa datetime.tzinfo która określa strefę czasową, z której należy zdekodować obiekty datetime. Domyślnie utc.

Korzystanie z python-bsonjs

python-bsonjs nie zależy od PyMongo i może zaoferować niezłą poprawę wydajności w stosunku do json_util :

bsonjs jest około 10-15 razy szybszy niż json_util PyMongo przy dekodowaniu BSON na JSON i kodowaniu JSON na BSON.

Uwaga:

  • aby efektywnie korzystać z bsonjs, zaleca się bezpośrednią pracę z RawBSONDocument
  • daty są kodowane przy użyciu reprezentacji LEGACY, tj. {"$date": <dateAsMilliseconds>} . Obecnie nie ma opcji, aby to zmienić.

Instalacja

pip install python-bsonjs

Stosowanie

Aby w pełni skorzystać z bsonjs, skonfiguruj bazę danych, aby RawBSONDocument klasy RawBSONDocument . Następnie użyj dumps aby przekonwertować surowe bajty bson na json i loads aby przekonwertować surowe bajty 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)

Korzystanie z modułu json z niestandardowymi programami obsługi

Jeśli wszystko, czego potrzebujesz, to serializacja wyników mongo do json, możliwe jest użycie modułu json , pod warunkiem, że zdefiniujesz niestandardowe programy obsługi do obsługi typów pól, których nie można serializować. Jedną z zalet jest to, że masz pełną moc kodowania określonych pól, takich jak reprezentacja daty i godziny.

Oto moduł obsługi, który koduje daty przy użyciu reprezentacji ISO i identyfikatora jako łańcucha szesnastkowego:

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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow