You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB GridFS存储大对象及Python提取异常问题排查

Java序列化日志到GridFS后,Python解析JSON失败

背景

每日生成外部REST调用的应用日志,需解析提取StartTime、响应EndTime、payload等信息,按会话整理后生成瀑布图可视化各调用耗时。单个会话的整理数据超过16MB,因此采用GridFS存储序列化后的自定义REST调用对象。

问题

在Jupyter Notebook中用Python提取数据时,返回内容带有String 7e0000前缀及大量转义斜杠,导致json.loads解析失败。

Python提取代码及输出

提取代码

import javaobj.v2 as javaobj
pObj = javaobj.loads(fs.get(record['calls']).read())
pObj.dump()

输出示例

'[String 7e0000: \'[{"tokenId":"a6fc52b3-0c60-4332-b866-09f3fe8b243f","responseTime":540.2587,"requestPayload":null,"responsePayload":"{\\"Identifiers\\":[{\\"Name\\":\\"XXXX MANAGEMENT LLC-CISA\\",\\"Number\\":\\"0012345\\",\\"SubNumber\\":\\"00099\\",\\"Sourceode\\":null,\\"SourceGroups\\":null,\\"IsPrimary\\":false}],\\"serviceConsumerId\\":\\"YYY\\",\\"serviceConsumerSystemId\\":\\"001\\",\\"service ....

Java端序列化及存储代码

自定义对象转String方法(未实际使用)

public static String convertToString(ArrayList<LogStructure> logs){
    StringBuilder sBuilder = new StringBuilder();
    sBuilder.append("[");
    for (LogStructure log: logs){
        sBuilder.append(getString(log));
        sBuilder.append(",");
    }
    return sBuilder.toString();
}

public static String getString(LogStructure log){
    StringBuilder sBuilder = new StringBuilder();
    sBuilder.append("{logLevel:");
    sBuilder.append(log.logLevel);
    sBuilder.append(",logInjestionDateTime:");
    sBuilder.append(log.logInjestionDateTime);
    sBuilder.append(",serverName:");
    sBuilder.append(log.serverName);

    sBuilder.append(",serviceName:");
    sBuilder.append(log.serviceName);

    sBuilder.append(",serviceEndPoint:");
    sBuilder.append(log.serviceEndPoint);

    sBuilder.append(",startTime:");
    sBuilder.append(log.startTime);

    sBuilder.append(",endTime:");
    sBuilder.append(log.endTime);

    sBuilder.append(",responseTime:");
    sBuilder.append(log.responseTime);

    sBuilder.append(",message:");
    sBuilder.append(log.message);

    sBuilder.append(",endTime:");
    sBuilder.append(log.endTime);

    sBuilder.append(",requestId:");
    sBuilder.append(log.requestId);

    sBuilder.append(",tokenId:");
    sBuilder.append(log.tokenId);

    sBuilder.append(",userId:");
    sBuilder.append(log.userId);

    sBuilder.append(",requestPayload:");
    sBuilder.append(log.requestPayload);

    sBuilder.append(",responsePayload:");
    sBuilder.append(log.responsePayload);

    sBuilder.append(",payloadType:");
    sBuilder.append(log.payloadType);
    sBuilder.append("}");

    return sBuilder.toString();
}

上传至GridFS代码(当前使用)

JSONArray list = new JSONArray();
for(LogStructure temp: tempObject){
    totalCalls++;
    JSONObject obj = new JSONObject();
    obj.put("logLevel", temp.logLevel);
    obj.put("logInjestionDateTime", temp.logInjestionDateTime);
    obj.put("serverName", temp.serverName);
    obj.put("serviceName", temp.serviceName);
    obj.put("serviceEndPoint", temp.serviceEndPoint);
    obj.put("startTime", temp.startTime);
    obj.put("endTime", temp.endTime);
    obj.put("responseTime", temp.responseTime);
    obj.put("message", temp.message);
    obj.put("requestId", temp.requestId);
    obj.put("tokenId", temp.tokenId);
    obj.put("requestPayload", temp.requestPayload);
    obj.put("responsePayload", temp.responsePayload);
    obj.put("payloadType", temp.payloadType);
    list.add(obj);
}

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos;
try {
     oos = new ObjectOutputStream(baos);
     oos.writeObject(list.toJSONString());
     oos.flush();
     oos.close();
} catch (IOException e) {
    e.printStackTrace();
}
InputStream is = new ByteArrayInputStream(baos.toByteArray());

GridFSBucket gridFSBucket = mongo.getGridFsBucket(mDb, "Logs");
ObjectId objectId = mongo.uploadToGrid(is, gridFSBucket);
doc.append("totalCalls", totalCalls);
doc.append("calls", objectId);
mongo.insertDocument(mCollection, doc);

已尝试的方案

  • 直接序列化ArrayList:Python提取时出现System.*.ArrayList标识,无法解析
  • 改用simple.json存储JsonObject:默认序列化后出现内存地址,无效
  • 使用toJSONString转成字符串存储:仍出现解析异常

问题原因分析

  1. 核心错误:Java端将list.toJSONString()生成的标准JSON字符串,通过ObjectOutputStream.writeObject()做了Java对象序列化,导致存储到GridFS的是Java序列化后的String对象,而非原始JSON文本。
  2. Python用javaobj读取后得到的是Java的String实例,因此输出带有String 7e0000这类Java对象标识,同时字符串内部的转义符被双重转义,导致json.loads无法识别。

解决方案

步骤1:修改Java端存储逻辑,直接存储原始JSON字符串

无需使用Java对象序列化,直接将JSON字符串写入GridFS:

JSONArray list = new JSONArray();
// 省略构建JSONArray的代码...

String jsonStr = list.toJSONString();
InputStream is = new ByteArrayInputStream(jsonStr.getBytes(StandardCharsets.UTF_8));

GridFSBucket gridFSBucket = mongo.getGridFsBucket(mDb, "Logs");
ObjectId objectId = mongo.uploadToGrid(is, gridFSBucket);
doc.append("totalCalls", totalCalls);
doc.append("calls", objectId);
mongo.insertDocument(mCollection, doc);

步骤2:Python端直接读取JSON字符串并解析

无需使用javaobj库,直接读取GridFS中的原始文本:

# 读取GridFS中的原始JSON内容
json_data = fs.get(record['calls']).read().decode('utf-8')
# 解析JSON
data = json.loads(json_data)

步骤3:处理残留转义问题(如果存在)

如果responsePayload这类字段内部还有转义的JSON字符串,可以二次解析:

for item in data:
    if item['responsePayload'] is not None:
        item['responsePayload'] = json.loads(item['responsePayload'])

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 05:08:18