You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何读取包含带数据类型括号值的非标准JSON文件?

哈哈,这个坑我踩过好多次——你手里的根本不是标准JSON,是MongoDB导出的那种带自定义类型标记的扩展格式,标准JSON解析器当然会报错。别慌,给你几个结构化的处理方案,按需选:

方法1:快速文本预处理(适合简单场景)

如果只是想把数据读出来,不需要保留原始类型信息,直接用正则把ISODate("xxx")ObjectId("xxx")这类标记替换成标准字符串就行。

举个Python实现的例子:

import re
import json

def fix_mongo_json(raw_text):
    # 把ISODate("时间字符串")替换成纯字符串
    text = re.sub(r'ISODate\("([^"]+)"\)', r'"\1"', raw_text)
    # 把ObjectId("ID字符串")替换成纯字符串
    text = re.sub(r'ObjectId\("([^"]+)"\)', r'"\1"', text)
    return text

# 使用示例
with open('your_file.json', 'r', encoding='utf-8') as f:
    raw_content = f.read()

processed_content = fix_mongo_json(raw_content)
parsed_data = json.loads(processed_content)

要是你想保留类型信息(比如之后要还原成MongoDB的类型),可以把替换规则改成生成带类型标识的对象:

text = re.sub(r'ISODate\("([^"]+)"\)', r'{"$type": "ISODate", "$value": "\1"}', raw_text)
text = re.sub(r'ObjectId\("([^"]+)"\)', r'{"$type": "ObjectId", "$value": "\1"}', raw_text)

方法2:用MongoDB官方工具/驱动(最靠谱的原生方案)

如果这个文件是直接从MongoDB导出的,那最稳妥的方式是用官方工具重新导出成标准JSON,或者直接用驱动读取数据,而不是处理这种非标准文件。

mongoexport导出标准JSON

在终端里执行:

mongoexport --db 你的数据库名 --collection 你的集合名 --output standard_json_file.json

导出的文件就是标准JSON,直接用任何解析器都能读。

用Python的pymongo直接读取数据

如果能连接到MongoDB,直接读数据再转成标准JSON更省心:

from pymongo import MongoClient
import json
from datetime import datetime

# 连接MongoDB
client = MongoClient('mongodb://localhost:27017/')
db = client['你的数据库名']
collection = db['你的集合名']

# 读取数据并转换为标准JSON格式
def serialize_mongo_doc(doc):
    # 把ObjectId转成字符串
    if '_id' in doc:
        doc['_id'] = str(doc['_id'])
    # 把ISODate转成ISO格式字符串
    for key, value in doc.items():
        if isinstance(value, datetime):
            doc[key] = value.isoformat()
    return doc

# 读取所有文档并序列化
all_docs = list(collection.find())
standard_data = [serialize_mongo_doc(doc) for doc in all_docs]

# 保存成标准JSON文件
with open('standard_output.json', 'w', encoding='utf-8') as f:
    json.dump(standard_data, f, indent=2)

方法3:自定义JSON解码器(保留类型信息)

如果必须处理现有文件,还想把ISODate转成Python的datetime对象、ObjectId转成bson的ObjectId对象,可以结合预处理和自定义解码器:

import re
import json
from datetime import datetime
from bson.objectid import ObjectId

def decode_mongo_types(obj):
    # 识别我们预处理时加的$type标记
    if '$type' in obj:
        if obj['$type'] == 'ISODate':
            # 把ISO字符串转成datetime对象
            return datetime.fromisoformat(obj['$value'].replace('Z', '+00:00'))
        elif obj['$type'] == 'ObjectId':
            # 转成ObjectId对象
            return ObjectId(obj['$value'])
    return obj

# 先预处理文本,把非标准类型转成带标记的对象
raw_text = open('your_file.json', 'r', encoding='utf-8').read()
processed_text = re.sub(r'ISODate\("([^"]+)"\)', r'{"$type": "ISODate", "$value": "\1"}', raw_text)
processed_text = re.sub(r'ObjectId\("([^"]+)"\)', r'{"$type": "ObjectId", "$value": "\1"}', processed_text)

# 用自定义解码器解析
parsed_data = json.loads(processed_text, object_hook=decode_mongo_types)

这样解析后的数据里,原来的ISODate会变成Python的datetimeObjectId会变成bson的ObjectId,方便后续和MongoDB交互。


内容的提问来源于stack exchange,提问作者HermanK

火山引擎 最新活动