如何使用 Python 将 MongoDB 的 bsondump 转换为 JSON?
Posted
技术标签:
【中文标题】如何使用 Python 将 MongoDB 的 bsondump 转换为 JSON?【英文标题】:How can I use Python to transform MongoDB's bsondump into JSON? 【发布时间】:2012-08-05 17:47:32 【问题描述】:所以我有大量来自 MongoDB 转储的 .bson。我在命令行上使用bsondump,将输出作为标准输入传送到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? (最终目标是将制表符分隔的数据流式传输到另一个数据库)
【问题讨论】:
你看过bson
吗? pypi.python.org/pypi/bson/0.3.2
除了删除 Mongo 依赖项之外还有什么作用吗?我不明白这怎么可能是我的问题,但我会再看一看。
Unable to deserialize PyMongo ObjectId from JSON的可能重复
我看到了那个并试图利用帮助。但是如果你注意到,他得到的字符串在 '_id' 前面有一个前面的 'u' 并且响应者指出它代表一个 python unicode 字符串
@boardrider 是吗?链接指向这个问题。
【参考方案1】:
您拥有的是 TenGen 模式下 Mongo Extended JSON 中的转储(请参阅here)。一些可能的方法:
如果可以再次转储,请通过 MongoDB REST API 使用严格输出模式。那应该给你真正的 JSON,而不是你现在拥有的。
使用来自http://pypi.python.org/pypi/bson/ 的bson
将您已有的BSON 读入Python 数据结构,然后对这些数据结构进行您需要的任何处理(可能输出JSON)。
使用 MongoDB Python 绑定连接到数据库以将数据导入 Python,然后执行您需要的任何处理。 (如果需要,您可以设置一个本地 MongoDB 实例并将转储的文件导入其中。)
将 Mongo 扩展 JSON 从 TenGen 模式转换为严格模式。您可以开发一个单独的过滤器来执行此操作(从 stdin 读取,将 TenGen 结构替换为 Strict 结构,并将结果输出到 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": "\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'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))
根据您的目标,其中之一应该是一个合理的起点。
【讨论】:
是的,我在我的问题中链接到了扩展 JSON 页面。我已经尝试过 BSON 库,但它没有实现我的目标。 bsondump 是我唯一可以开始工作的东西,但它给了我一个字符串。转储或重新加载数据不是可行的选择。 @PeterNachbaur:我在答案中添加了一个选项,以展示如何将 TenGen JSON 格式转换为 Strict JSON。这就是你的想法吗? 感谢您继续提供帮助 :) 现在负载正常了。最后,我假设您的意思是 json.dumps 而不是 json_util.dumps (后者似乎不存在),但这不起作用。但是,我不确定我现在是否需要它,因为我有一个字典。干杯! @PeterNachbaur:没问题,想想这个很有趣! :) 奇怪,我有一个 bson.json_util.dumps 函数。但也许它只存在于 mongo-python 代码的开发分支中。无论如何,你已经掌握了字典,所以你现在可以做任何你想做的事情;)祝你好运! 不错的方法。正则表达式:)【参考方案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。
【讨论】:
那个 for 循环不起作用 :( Traceback(最近一次调用最后一次):文件“您可以去除数据类型并使用正则表达式获取严格的 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
【讨论】:
以上是关于如何使用 Python 将 MongoDB 的 bsondump 转换为 JSON?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 NOT (A AND B) 转换为 mongodb 查询
如何使用python有效地将国家信息添加到包含mongoDB中坐标的文档?
如何使用Python将Ansible std_outlines输出JSON插入MongoDB中