Как я могу использовать Python для преобразования bsondump MongoDB в JSON?

поэтому у меня огромное количество .bson из свалки MongoDB. Я использую bsondump в командной строке передайте вывод как stdin на python. Это успешно преобразуется из BSON в "JSON", но на самом деле это строка и, по-видимому, не законный JSON.

например, входящая строка выглядит так:

{ "_id" : ObjectId( "4d9b642b832a4c4fb2000000" ),
  "acted_at" : Date( 1302014955933 ),
  "created_at" : Date( 1302014955933 ),
  "updated_at" : Date( 1302014955933 ),
  "_platform_id" : 3,
  "guid" : 72106535190265857 }

который, я полагаю,Монго расширенный JSON.

когда я читаю такие строки и do:

json_line = json.dumps(line)

Я:

"{ "_id" : ObjectId( "4d9b642b832a4c4fb2000000" ),
"acted_at" : Date( 1302014955933 ),
"created_at" : Date( 1302014955933 ),
"updated_at" : Date( 1302014955933 ),
"_platform_id" : 3,
"guid" : 72106535190265857 }n"

что равно <type 'str'>.

Я также пробовал

json_line = json.dumps(line, default=json_util.default)

(см. pymongo json_util-обнаружение спама предотвращает третью ссылку ) Который, похоже, выводит то же самое, что и дампы выше. нагрузки выдает ошибку:

json_line = json.loads(line, object_hook=json_util.object_hook)
ValueError: No JSON object could be decoded

Итак, как я могу преобразовать строку TenGen JSON в разбираемый JSON? (конечная цель-поток данных, разделенных вкладками, в другую базу данных)

3 ответов


у вас есть дамп в Mongo Extended JSON в режиме Тенгена (см. здесь). Несколько возможных путей:

  1. Если вы можете сбросить снова, используйте строгий режим вывода через API REST MongoDB. Это должно дать вам настоящий JSON вместо того, что у вас есть сейчас.

  2. использовать bson от http://pypi.python.org/pypi/bson/ Чтобы прочитать BSON, который у вас уже есть в структурах данных Python, а затем выполнить любую обработку нужно на тех (возможно, вывод JSON).

  3. используйте привязки MongoDB Python для подключения к базе данных, чтобы получить данные в Python, а затем выполните любую обработку. (При необходимости вы можете настроить локальный экземпляр MongoDB и импортировать в него сброшенные файлы.)

  4. преобразуйте Mongo Extended JSON из режима TenGen в строгий режим. Вы можете разработать отдельный фильтр для этого (прочитайте из stdin, замените структуры TenGen строгими структуры и вывод результата на stdout), или вы можете сделать это по мере обработки ввода.

вот пример использования Python и регулярных выражений:

import json, re
from bson import json_util

with open("data.tengenjson", "rb") as f:
    # read the entire input; in a real application,
    # you would want to read a chunk at a time
    bsondata = f.read()

    # convert the TenGen JSON to Strict JSON
    # here, I just convert the ObjectId and Date structures,
    # but it's easy to extend to cover all structures listed at
    # http://www.mongodb.org/display/DOCS/Mongo+Extended+JSON
    jsondata = re.sub(r'ObjectId\s*\(\s*\"(\S+)\"\s*\)',
                      r'{"$oid": ""}',
                      bsondata)
    jsondata = re.sub(r'Date\s*\(\s*(\S+)\s*\)',
                      r'{"$date": }',
                      jsondata)

    # now we can parse this as JSON, and use MongoDB's object_hook
    # function to get rich Python data structures inside a dictionary
    data = json.loads(jsondata, object_hook=json_util.object_hook)

    # just print the output for demonstration, along with the type
    print(data)
    print(type(data))

    # serialise to JSON and print
    print(json_util.dumps(data))

в зависимости от вашей цели, один из них должен быть разумной отправной точкой.


загрузка всего документа bson в память python стоит дорого.

Если вы хотите передать его, а не загружать весь файл и загружать все, вы можете попробовать эту библиотеку.

https://github.com/bauman/python-bson-streaming

from bsonstream import KeyValueBSONInput
from sys import argv
for file in argv[1:]:
    f = open(file, 'rb')
    stream = KeyValueBSONInput(fh=f,  fast_string_prematch="somthing") #remove fast string match if not needed
    for id, dict_data in stream:
        if id:
         ...process dict_data...

вы можете конвертировать строки файла bson следующим образом:

>>> import bson
>>> bs = open('file.bson', 'rb').read()
>>> for valid_dict in bson.decode_all( bs ):
....

каждый элемент valid_dict будет допустимым Python dict, который можно преобразовать в json.