Поиск…


Вступление

Во многих приложениях записи из MongoDB должны быть сериализованы в формате JSON. Если в ваших записях есть поля типа date, datetime, objectId, binary, code и т. Д., Вы столкнетесь с TypeError: not JSON serializable исключениями при использовании json.dumps . В этом разделе показано, как преодолеть это.

Использование json_util

json_util предоставляет два вспомогательных метода, dumps и loads , которые переносят собственные методы json и обеспечивают явное преобразование BSON в json и из него.

Простое использование

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

если record :

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

то json_str становится:

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

JSONOptions

Можно настроить поведение dumps через объект JSONOptions . Доступны два набора параметров: DEFAULT_JSON_OPTIONS и 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>) 

Чтобы использовать различные параметры, вы можете:

  1. измените объект DEFAULT_JSON_OPTIONS . В этом случае параметры будут использоваться для всех последующих вызовов для dumps :

     from bson.json_util import DEFAULT_JSON_OPTIONS
     DEFAULT_JSON_OPTIONS.datetime_representation = 2
     dumps(record)
    
  2. укажите JSONOptions при вызове dumps используя параметр 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)
    

Параметры JSONOptions :

  • strict_number_long : Если значение true, объекты Int64 кодируются в тип Strong Mode в расширенном JSON типа LongLong, то есть {"$numberLong": "<number>" } . В противном случае они будут закодированы как int. По умолчанию False.
  • datetime_representation : представление, которое следует использовать при кодировании экземпляров datetime.datetime. 0 => {"$date": <dateAsMilliseconds>} , 1 => {"$date": {"$numberLong": "<dateAsMilliseconds>"}} , 2 => {"$date": "<ISO-8601>"}
  • strict_uuid : Если true, объект uuid.UUID закодирован в двоичный файл режима MonoDB Extended JSON Strict. В противном случае он будет закодирован как {"$uuid": "<hex>" } . По умолчанию False.
  • document_class : документы BSON, возвращаемые load (), будут декодированы в экземпляр этого класса. Должен быть подкласс коллекций. MutableMapping. По умолчанию dict.
  • uuid_representation : представление BSON для использования при кодировании и декодировании экземпляров uuid.UUID. По умолчанию используется значение PYTHON_LEGACY.
  • tz_aware : Если значение true, то значение типа MonoDB Extended JSON's Strict типа будет декодировано для экземпляров datetime.datetime, относящихся к часовому поясу . В противном случае они будут наивными. По умолчанию используется значение True.
  • tzinfo : подкласс datetime.tzinfo который указывает часовой пояс, из которого должны быть декодированы объекты datetime. По умолчанию utc.

Использование python-bsonjs

python-bsonjs не зависит от PyMongo и может предложить хорошее улучшение производительности по сравнению с json_util :

bsonjs примерно на 10-15 раз быстрее, чем у json_util от PyMongo при декодировании BSON на JSON и кодировании JSON на BSON.

Обратите внимание, что:

  • для эффективного использования bsonjs рекомендуется работать непосредственно с RawBSONDocument
  • даты кодируются с использованием представления LEGACY, то есть {"$date": <dateAsMilliseconds>} . В настоящее время нет возможности изменить это.

Монтаж

pip install python-bsonjs

использование

Чтобы полностью использовать преимущества bsonjs, настройте базу данных для использования класса RawBSONDocument . Затем используйте dumps для преобразования bson raw bytes в json и loads для преобразования json в bson raw bytes:

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)

Использование json-модуля с пользовательскими обработчиками

Если все, что вам нужно, сериализует результаты mongo в json, можно использовать модуль json , если вы определяете пользовательские обработчики для работы с типами несериализуемых полей. Одно из преимуществ заключается в том, что у вас есть полная сила в том, как вы кодируете определенные поля, например представление даты и времени.

Вот обработчик, который кодирует даты с использованием iso-представления и id как шестнадцатеричную строку:

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
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow