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

Java树形Node对象转JSON时OOM异常的解决方案咨询

解决树形结构转JSON的OOM问题方案

核心思路是避免在内存中构建完整JSON对象,采用流式API逐节点写入,无论树的规模多大,内存仅需存储当前遍历的节点。

1. Gson流式写入方案(适配你已使用的Gson)

直接使用Gson底层的JsonWriter配合深度优先遍历,边遍历树边写入JSON,全程内存占用极低:

代码实现

import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.List;

public class NodeJsonSerializer {
    public void serialize(Node root, Writer writer) throws IOException {
        JsonWriter jsonWriter = new JsonWriter(writer);
        // 可选:开启缩进格式化JSON,不需要可删除
        jsonWriter.setIndent("  ");
        serializeNode(root, jsonWriter);
        jsonWriter.close();
    }

    private void serializeNode(Node node, JsonWriter jsonWriter) throws IOException {
        jsonWriter.beginObject();
        
        // 写入name字段
        jsonWriter.name("name").value(node.name);
        
        // 写入children数组
        jsonWriter.name("children");
        jsonWriter.beginArray();
        if (node.children != null) {
            for (Node child : node.children) {
                serializeNode(child, jsonWriter);
            }
        }
        jsonWriter.endArray();
        
        // 写入values数组
        jsonWriter.name("values");
        jsonWriter.beginArray();
        if (node.values != null) {
            for (Object value : node.values) {
                // Gson自动适配基本类型、字符串等对象的写入
                jsonWriter.value(value);
            }
        }
        jsonWriter.endArray();
        
        jsonWriter.endObject();
    }
}

使用方式

直接传入输出流(如文件流、网络流),无需在内存中缓存完整JSON:

// 示例:写入到本地文件
try (FileWriter writer = new FileWriter("output.json")) {
    new NodeJsonSerializer().serialize(rootNode, writer);
} catch (IOException e) {
    e.printStackTrace();
}

2. 额外排查优化点

如果流式方案仍出现OOM,检查以下问题:

  • 循环引用:树中是否存在父节点引用子节点、子节点反向引用父节点的情况?可通过Set记录已访问节点的唯一标识,避免无限遍历。
  • 大对象存储:values列表中的对象是否为大字节数组、超大字符串?这类对象可单独处理(如写入磁盘后在JSON中存路径),若必须存入JSON,流式写入仍能支撑,但需确保Writer的缓冲区不要过大。
  • JVM堆内存配置:可临时调整堆内存参数(如-Xmx4g)验证,但流式方案才是根本解决方式。

3. 替代方案:Jackson流式API

若愿意更换JSON库,Jackson的JsonGenerator同样支持流式写入,逻辑与Gson一致:

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import java.io.IOException;
import java.io.Writer;

public class NodeJacksonSerializer {
    public void serialize(Node root, Writer writer) throws IOException {
        JsonFactory factory = new JsonFactory();
        try (JsonGenerator gen = factory.createGenerator(writer)) {
            gen.useDefaultPrettyPrinter(); // 可选格式化
            serializeNode(root, gen);
        }
    }

    private void serializeNode(Node node, JsonGenerator gen) throws IOException {
        gen.writeStartObject();
        gen.writeStringField("name", node.name);
        
        gen.writeFieldName("children");
        gen.writeStartArray();
        if (node.children != null) {
            for (Node child : node.children) {
                serializeNode(child, gen);
            }
        }
        gen.writeEndArray();
        
        gen.writeFieldName("values");
        gen.writeStartArray();
        if (node.values != null) {
            for (Object value : node.values) {
                gen.writeObject(value);
            }
        }
        gen.writeEndArray();
        
        gen.writeEndObject();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 21:55:27