使用Jackson解析嵌套数组HTTP响应提取Report ID
使用Jackson提取嵌套JSON数组中的所有Report ID
我来帮你搞定这个Jackson处理嵌套JSON的问题,你遇到的核心是多层数组嵌套的遍历提取,我给你两种实用的解决方案,分别适合不同场景:
方案一:直接使用Jackson的JsonNode进行树遍历(无需POJO)
如果只是临时提取数据,不想创建一堆实体类,这种方法最快捷。你可以先把已有的edges字段对应的JSON节点拿出来,然后逐层遍历嵌套的数组:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.ArrayList; import java.util.List; public class ReportIdExtractor { public static void main(String[] args) throws Exception { // 假设你已经获取到最外层的edges节点(JsonNode类型) JsonNode outerEdges = ...; // 这里替换成你实际拿到的edges节点 ObjectMapper mapper = new ObjectMapper(); List<String> reportIds = new ArrayList<>(); // 遍历外层stixDomainEntities的edges数组 for (JsonNode outerEdge : outerEdges) { // 获取node下的reports节点 JsonNode reports = outerEdge.get("node").get("reports"); if (reports != null && reports.has("edges")) { // 遍历reports的edges数组 for (JsonNode reportEdge : reports.get("edges")) { // 提取id字段并加入列表 JsonNode idNode = reportEdge.get("node").get("id"); if (idNode != null && !idNode.isNull()) { reportIds.add(idNode.asText()); } } } } // 输出所有提取到的ID System.out.println("提取到的Report ID列表:"); reportIds.forEach(System.out::println); } }
这种方法的好处是灵活,不需要提前定义实体类,适合快速处理结构不固定的JSON。
方案二:通过POJO映射实现类型安全的提取(推荐长期维护场景)
如果你的JSON结构是固定的,创建对应的实体类可以让代码更清晰、类型更安全,避免空指针风险:
首先定义对应的实体类:
// 最外层的Edge(对应stixDomainEntities的edges元素) public class StixDomainEntityEdge { private StixDomainNode node; // getter和setter public StixDomainNode getNode() { return node; } public void setNode(StixDomainNode node) { this.node = node; } } // StixDomainNode,包含reports字段 public class StixDomainNode { private ReportContainer reports; // getter和setter public ReportContainer getReports() { return reports; } public void setReports(ReportContainer reports) { this.reports = reports; } } // 包含reports的edges数组的容器 public class ReportContainer { private List<ReportEdge> edges; // getter和setter public List<ReportEdge> getEdges() { return edges; } public void setEdges(List<ReportEdge> edges) { this.edges = edges; } } // Report的Edge元素 public class ReportEdge { private ReportNode node; // getter和setter public ReportNode getNode() { return node; } public void setNode(ReportNode node) { this.node = node; } } // 最终包含ID的ReportNode public class ReportNode { private String id; // getter和setter public String getId() { return id; } public void setId(String id) { this.id = id; } }
然后编写提取逻辑:
import com.fasterxml.jackson.databind.ObjectMapper; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class ReportIdExtractorWithPOJO { public static void main(String[] args) throws Exception { // 假设你已经获取到最外层edges对应的JSON字符串或JsonNode String outerEdgesJson = ...; // 替换成你实际的JSON内容 ObjectMapper mapper = new ObjectMapper(); // 反序列化为StixDomainEntityEdge的列表 List<StixDomainEntityEdge> outerEdgesList = mapper.readValue(outerEdgesJson, mapper.getTypeFactory().constructCollectionType(List.class, StixDomainEntityEdge.class)); // 提取所有Report ID List<String> reportIds = new ArrayList<>(); for (StixDomainEntityEdge outerEdge : outerEdgesList) { if (outerEdge.getNode() != null && outerEdge.getNode().getReports() != null) { List<ReportEdge> reportEdges = outerEdge.getNode().getReports().getEdges(); if (reportEdges != null) { // 遍历每个report edge提取ID List<String> ids = reportEdges.stream() .filter(reportEdge -> reportEdge.getNode() != null) .map(reportEdge -> reportEdge.getNode().getId()) .filter(id -> id != null) .collect(Collectors.toList()); reportIds.addAll(ids); } } } // 输出结果 System.out.println("提取到的Report ID列表:"); reportIds.forEach(System.out::println); } }
这种方法的优势是类型安全,IDE会帮你检查字段名是否正确,后期JSON结构如果有小变化,修改实体类即可,代码可读性更高。
两种方案都能处理多个报告的情况,不管你的数组里有多少个元素,都会遍历提取所有的ID。
内容的提问来源于stack exchange,提问作者ansem90




