Как я могу использовать Python для преобразования MongoDB bsondump в 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 }
Я верю Mongo Extended JSON.
Когда я читаю в такой строке и делаю:
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?
(конечная цель состоит в том, чтобы передать данные, разделенные вкладкой, в другую базу данных).
Ответы
Ответ 1
У вас есть свалка в Mongo Extended JSON в режиме TenGen (см. здесь). Некоторые возможные способы:
-
Если вы можете снова сбросить, используйте режим Strict output через API REST MongoDB. Это должно дать вам настоящий JSON вместо того, что у вас есть.
-
Используйте bson
из http://pypi.python.org/pypi/bson/, чтобы прочитать BSON, который у вас уже есть, в структурах данных Python, а затем выполните любую необходимую вам обработку (возможно выводя JSON).
-
Используйте привязки Python MongoDB для подключения к базе данных, чтобы получить данные на Python, а затем выполните любую необходимую обработку. (Если необходимо, вы можете настроить локальный экземпляр MongoDB и импортировать свои сбрасываемые файлы в это.)
-
Преобразуйте Mongo Extended JSON из режима TenGen в режим Strict. Вы можете создать отдельный фильтр для этого (прочитайте с 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 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": "\1"}',
bsondata)
jsondata = re.sub(r'Date\s*\(\s*(\S+)\s*\)',
r'{"$date": \1}',
jsondata)
# now we can parse this as JSON, and use MongoDB 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))
В зависимости от вашей цели, одна из них должна быть разумной отправной точкой.
Ответ 2
Загрузка всего документа 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...
Ответ 3
Вы можете преобразовать строки файла bson следующим образом:
>>> import bson
>>> bs = open('file.bson', 'rb').read()
>>> for valid_dict in bson.decode_all( bs ):
....
Каждый элемент valid_dict будет действительным директором python, который вы можете преобразовать в json.
Ответ 4
Вы можете удалить типы данных и получить строгий JSON с регулярным выражением:
import json
import re
#This will outputs a iterator that converts each file line into a dict.
def readBsonFile(filename):
with open(filename, "r") as data_in:
for line in data_in:
# convert the TenGen JSON to Strict JSON
jsondata = re.sub(r'\:\s*\S+\s*\(\s*(\S+)\s*\)',
r':\1',
line)
# parse as JSON
line_out = json.loads(jsondata)
yield line_out