大哥们,给菜鸟想想办法吧,求求了。

184 天前
 yoloMiss
问题是这个样子的:
自己写的一个 springboot 程序,接受其他业务系统的数据,60m ,但是由于一些要求数据中的某些字段要求被移除,这里我就非常“合理”的将数据转成 jsonobject ,然后再通过 new jsonarray 逐步获取里面的每一条数据,然后这个时候就又非常“合理”的 oom 了。
大概示例就是下面这个样子:
httpReponse res = httpUtil.get(url);
String resStr = res.getBody();
JSONArray arrayData = JSONArray.parse(resStr);
for(int i=0,i<arrayData.size,i++){
JSONObject jsonData = arrayData.getJSONObject(i);
if(jsonData.contains("key")){
jsonData.remove(i)
}
}
目前使用的 json 工具是 fastjson ,有没有希望通过升级版本解决这个问题?或者其他方案呢?
至于怎么排查 oom 的位置,这个不太好弄(不是我不会!是一些原因限制目前只能看着代码猜测,一点一点试),也不能贴报错的图。
3784 次点击
所在节点    Java
19 条回复
blankmiss
184 天前
等一下 我含根内存条 用大脑运算一下这段程序
yoloMiss
184 天前
@blankmiss 哈哈哈,扩内存当然可以。但是吧,不是那么的让感觉优雅。
blankmiss
184 天前
看来你没懂我的意思
yoloMiss
184 天前
@blankmiss 讲讲!分享一下你的方案。
lizardll
184 天前
这段代码中有几个明显的问题:

1. **循环变量语法错误**:
```java
for(int i=0,i<arrayData.size,i++)
```
应该修改为:
```java
for(int i=0; i<arrayData.size(); i++)
```

2. **删除 JSONArray 中的元素问题**: 当你从`JSONArray`中删除元素时,该数组的大小会改变,这可能会导致你错过某些元素或者遇到`IndexOutOfBoundsException`。一种解决方法是反向遍历这个数组。

3. **`JSONObject.contains`**:
根据我的最后的知识,`JSONObject`并没有`contains`方法。如果你想检查一个`JSONObject`是否包含某个 key ,你应该使用`has`方法:
```java
if(jsonData.has("key"))
```

4. **丢失分号**:
```java
jsonData.remove(i)
```
应该有一个分号:
```java
jsonData.remove(i);
```

5. **删除元素的方法不正确**:
使用`jsonData.remove(i)`是错误的。这将试图从`JSONObject`中删除键为`i`的项,而不是从`JSONArray`中删除索引为`i`的项。你应该在`arrayData`上调用`remove`方法,如`arrayData.remove(i)`。

考虑上述问题,修改后的代码如下:

```java
httpReponse res = httpUtil.get(url);
String resStr = res.getBody();
JSONArray arrayData = JSONArray.parse(resStr);
for(int i = arrayData.size() - 1; i >= 0; i--) {
JSONObject jsonData = arrayData.getJSONObject(i);
if(jsonData.has("key")) {
arrayData.remove(i);
}
}
```

请确保你的代码环境中的库方法与我的建议相匹配,不同的库可能有不同的方法名称和功能。
lizardll
184 天前
这不是问问 gpt 就能解决
lizardll
184 天前
httpReponse res = httpUtil.get(url);
String resStr = res.getBody();
JSONArray arrayData = JSONArray.parse(resStr);
我是建议你用迭代器写

Iterator<Object> it = arrayData.iterator();
while (it.hasNext()) {
JSONObject jsonData = (JSONObject) it.next();
if (jsonData.has("key")) {
it.remove();
}
}
knightdf
184 天前
chunk
guyeu
184 天前
gpt 弄混了不同的 json 库,JSONObject 当然有 contains 方法,它实现了 Map 接口。你这里明显的问题是在遍历的时候删除元素,JSONObject 内部的实现不可预期,所以有可能是这块的问题。
stinkytofu
184 天前
60M 的 JSON 再转 java 对象处理起来太消耗性能了, 建议用纯文本的方式处理, 只是移出特定的字段, 正则表达式很好写
silentsky
184 天前
楼上说的对 别转 JSON 对象了 直接处理字符串
skydiver
184 天前
@lizardll 没记错的话这个网站禁止贴 ChatGPT 生成的内容
blankmiss
184 天前
@lizardll 被站长看到会 ban 号
chuck1in
184 天前
op 为啥这么着急
BQsummer
184 天前
试试 Gson 吧, 支持流式读取:
JsonReader reader = new JsonReader(new InputStreamReader(inputStream));
reader.beginArray();
missya
184 天前
fastjson 也支持流式读取吧,比一次性加载全量数据到内存中
lff0305
183 天前
把这个 json array 存储到 elastic search 里面,使用 elastic search 的运算符进行过滤,更新,最后导出
knva
183 天前
流式读取,直接处理字符串
James2099
183 天前
httpResponse res = httpUtil.get(url);
String resStr = res.getBody();
JSONArray arrayData = JSONArray.parseArray(resStr);
for (int i = 0; i < arrayData.size(); i++) {
JSONObject jsonData = arrayData.getJSONObject(i);
if (jsonData.containsKey("key")) {
jsonData.remove("key");
}
}
流式 API 处理 JSON ,这样:



httpResponse res = httpUtil.get(url);
String resStr = res.getBody();
JSONReader reader = new JSONReader(new StringReader(resStr));
reader.startArray();
while (reader.hasNext()) {
JSONObject jsonData = reader.readObject();
jsonData.remove("key");
// 处理 jsonData
}
reader.endArray();
reader.close();

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/988843

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX