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

如何用Jackson优先读取大JSON文件末尾的Node1.3节点

解决方案:流式解析大JSON并关联日期到数组元素

针对你处理65MB大JSON文件的场景,我给你优化了Jackson的流式解析逻辑,既能高效读取又能按要求先获取日期再处理数组元素。下面是具体实现步骤:

1. 定义目标POJO

首先创建一个POJO类,用来存储最终需要的关联数据:

public class LogEntry {
    private String logLevel;
    private int count;
    private String fromDate;
    private String toDate;

    // 无参构造函数(Jackson解析必须)
    public LogEntry() {}

    // Getter和Setter方法
    public String getLogLevel() { return logLevel; }
    public void setLogLevel(String logLevel) { this.logLevel = logLevel; }
    public int getCount() { return count; }
    public void setCount(int count) { this.count = count; }
    public String getFromDate() { return fromDate; }
    public void setFromDate(String fromDate) { this.fromDate = fromDate; }
    public String getToDate() { return toDate; }
    public void setToDate(String toDate) { this.toDate = toDate; }

    // 可选:重写toString方便调试
    @Override
    public String toString() {
        return "LogEntry{" +
                "logLevel='" + logLevel + '\'' +
                ", count=" + count +
                ", fromDate='" + fromDate + '\'' +
                ", toDate='" + toDate + '\'' +
                '}';
    }
}

2. 优化流式解析代码

修改原有的解析逻辑,重点解决层级遍历和日期缓存的问题,同时跳过无关节点提升效率:

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.File;
import java.io.IOException;

public class TempMain {
    public static void main(String[] args) throws IOException {
        JsonFactory jfactory = new JsonFactory();
        ObjectMapper mapper = new ObjectMapper();
        String fromDate = null;
        String toDate = null;

        try (JsonParser jParser = jfactory.createParser(new File("/tmp/file.json"))) {
            // 遍历根对象,找到"Root Node"
            while (jParser.nextToken() != JsonToken.END_OBJECT) {
                String rootField = jParser.getCurrentName();
                if ("Root Node".equals(rootField)) {
                    jParser.nextToken(); // 进入Root Node的对象节点
                    // 遍历Root Node下的字段,找到"Node1"
                    while (jParser.nextToken() != JsonToken.END_OBJECT) {
                        String node1Field = jParser.getCurrentName();
                        if ("Node1".equals(node1Field)) {
                            jParser.nextToken(); // 进入Node1的对象节点
                            // 遍历Node1下的所有子节点
                            while (jParser.nextToken() != JsonToken.END_OBJECT) {
                                String node1ChildField = jParser.getCurrentName();
                                jParser.nextToken(); // 移动到当前字段的值位置

                                if ("Node1.3".equals(node1ChildField)) {
                                    // 解析日期节点,缓存fromDate和toDate
                                    ObjectNode dateNode = mapper.readTree(jParser);
                                    fromDate = dateNode.get("fromDate").asText();
                                    toDate = dateNode.get("toDate").asText();
                                } else if ("Node1.1".equals(node1ChildField)) {
                                    // 处理日志数组,逐个解析元素并关联日期
                                    if (jParser.getCurrentToken() == JsonToken.START_ARRAY) {
                                        while (jParser.nextToken() != JsonToken.END_ARRAY) {
                                            if (jParser.getCurrentToken() == JsonToken.START_OBJECT) {
                                                LogEntry entry = mapper.readValue(jParser, LogEntry.class);
                                                // 将缓存的日期赋值给当前日志条目
                                                entry.setFromDate(fromDate);
                                                entry.setToDate(toDate);
                                                // 这里添加你的业务逻辑,比如保存到数据库或集合
                                                System.out.println(entry);
                                            }
                                        }
                                    }
                                } else {
                                    // 跳过不需要的节点(比如Node1.2),减少不必要的解析
                                    jParser.skipChildren();
                                }
                            }
                        } else {
                            // 跳过Root Node下无关的节点
                            jParser.skipChildren();
                        }
                    }
                } else {
                    // 跳过根对象下无关的节点
                    jParser.skipChildren();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

关键优化点说明

  • 层级精准遍历:原代码直接在根对象查找子字段,会遗漏嵌套在Root Node->Node1下的目标节点,现在逐层进入嵌套对象,确保能正确捕获Node1.3和Node1.1。
  • 日期提前缓存:遇到Node1.3时立即解析并保存日期,后续处理数组时直接复用,不需要重复读取。
  • 高效跳过无关节点:使用jParser.skipChildren()跳过不需要的节点(如Node1.2),避免浪费资源解析无关内容,尤其适合大文件场景。
  • 低内存流式处理:逐个解析数组元素,不会将整个65MB的JSON加载到内存,保证解析过程的内存友好性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:29:26