如何在 Python 中读取包含 ObjectId 和 ISODate 的 json 文件?

Roc*_*ain 5 python json pymongo python-3.x

我想读取一个包含 ObjectId 和 ISODate 的 JSON 文件。

JSON 数据:

{
    "_id" : ObjectId("5baca841d25ce14b7d3d017c"),
    "country" : "in",
    "state" : "",
    "date" : ISODate("1902-01-31T00:00:00.000Z")
}
Run Code Online (Sandbox Code Playgroud)

Cri*_*oro 6

我想通过添加其他几个问题的一些注释来对Maviles答案进行一些扩展。

\n\n

首先,从 \xc2\xab Unable to deserialize PyMongo ObjectId from JSON \xc2\xbb 中我们了解到该数据看起来像实际 BSON/MOngo Extended JSON 对象的 Python 表示。本机 BSON 文件也是二进制文件,而不是文本。

\n\n

其次,来自\xc2\xab如何使用Python将MongoDB的bsondump转换为JSON?\xc2\xbb 我们可以扩展Fabian Fagerholm的答案:

\n\n
def read_mongoextjson_file(filename):\n    with open(filename, "r") as f:\n        # read the entire input; in a real application,\n        # you would want to read a chunk at a time\n        bsondata = \'[\'+f.read()+\']\'\n\n        # convert the TenGen JSON to Strict JSON\n        # here, I just convert the ObjectId and Date structures,\n        # but it\'s easy to extend to cover all structures listed at\n        # http://www.mongodb.org/display/DOCS/Mongo+Extended+JSON\n        jsondata = re.sub(r\'ObjectId\\s*\\(\\s*\\"(\\S+)\\"\\s*\\)\',\n                          r\'{"$oid": "\\1"}\',\n                          bsondata)\n        jsondata = re.sub(r\'ISODate\\s*\\(\\s*(\\S+)\\s*\\)\',\n                          r\'{"$date": \\1}\',\n                          jsondata)\n        jsondata = re.sub(r\'NumberInt\\s*\\(\\s*(\\S+)\\s*\\)\',\n                          r\'{"$numberInt": "\\1"}\',\n                          jsondata)\n\n        # now we can parse this as JSON, and use MongoDB\'s object_hook\n        # function to get rich Python data structures inside a dictionary\n        data = json.loads(jsondata, object_hook=json_util.object_hook)\n\n        return data\n
Run Code Online (Sandbox Code Playgroud)\n\n

正如您所看到的,比较前一个版本和这个版本,处理类型非常简单。对于您需要的任何其他内容,请使用MongoDB 扩展 JSON 参考

\n\n

一些额外的警告:

\n\n
    \n
  • 我正在处理的文件是一系列对象,但它不是列表,我通过将所有内容放在方括号中来解决:
  • \n
\n\n
   bsondata = \'[\'+f.read()+\']\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

JSONDecodeError: Extra data: line 38 column 2 (char 1016)否则我会在第一个对象的末尾得到 a 。

\n\n\n\n
pip uninstall bson\npip uninstall pymongo\npip install pymongo\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是带有完整工作示例的粘贴。

\n


Mav*_*les 1

我遇到了同样的问题,并且 bson 包只有在您已经拥有 dict 类型的数据时才会有帮助。

如果你已经将它存储在字典中,你可以将其转换为 json,如下所示(链接):

from bson import json_util
import json

resulting_json = json.dumps(your_dict, default=json_util.default)
Run Code Online (Sandbox Code Playgroud)

如果你将它作为字符串,bson 将无济于事。所以我只是删除了对象并制作了一个严格的 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
Run Code Online (Sandbox Code Playgroud)

一个包含以下内容的文件:

{ "_id" : ObjectId("5baca841d25ce14b7d3d017c"), "country" : "in", "state" : "", "date" : ISODate("1902-01-31T00:00:00.000Z")}
Run Code Online (Sandbox Code Playgroud)

将输出这个字典:

     {  "_id" : "5baca841d25ce14b7d3d017c",
        "country" : "in",
        "state" : "",
        "date" : "1902-01-31T00:00:00.000Z"}
Run Code Online (Sandbox Code Playgroud)