Java如何遍历多层嵌套JSON(含对象与数组)并统计不同类型数量
解决方案
核心问题是你原来的代码将JSON节点value直接转为字符串存储,丢失了嵌套结构信息,无法继续内层遍历。可以通过类型判断+递归遍历实现全层级扫描,调整后的完整代码如下:
package com.mycompany.app; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import java.io.FileReader; import java.util.HashMap; import java.util.Map; public class App { // 存储.type的统计结果 private static Map<String, Integer> typeCountMap = new HashMap<>(); @SuppressWarnings("unchecked") public static void main(String[] args) throws Exception { String filePath = "D:/sandbox/map03/my-app/data.json"; // 解析JSON文件 Object obj = new JSONParser().parse(new FileReader(filePath)); JSONObject root = (JSONObject) obj; // 获取data节点 Map<String, Object> dataMap = (Map<String, Object>) root.get("data"); System.out.println("--------------------------------------------------------------------"); // 遍历data下的第一层节点,同时打印你需要的输出 for (Map.Entry<String, Object> entry : dataMap.entrySet()) { System.out.println(String.format("Key is: %s, Value is : %s", entry.getKey(), entry.getValue())); // 递归遍历每个节点的内层结构 traverseNode(entry.getValue()); } System.out.println("--------------------------------------------------------------------"); // 输出统计结果,可根据需求调整switch逻辑 System.out.println(".type字段统计结果:"); for (Map.Entry<String, Integer> countEntry : typeCountMap.entrySet()) { switch (countEntry.getKey()) { case "inet4": System.out.println("IPV4地址类型出现次数:" + countEntry.getValue()); break; case "uri": System.out.println("URI类型出现次数:" + countEntry.getValue()); break; case "bigdec": System.out.println("高精度数字类型出现次数:" + countEntry.getValue()); break; default: System.out.println("未知类型" + countEntry.getKey() + "出现次数:" + countEntry.getValue()); } } } /** * 递归遍历JSON节点,统计.type字段 * @param node 当前遍历的JSON节点 */ @SuppressWarnings("unchecked") private static void traverseNode(Object node) { // 节点是JSONObject类型(即{}包裹的对象) if (node instanceof Map) { Map<String, Object> jsonObj = (Map<String, Object>) node; // 检查是否包含.type字段 if (jsonObj.containsKey(".type")) { String type = jsonObj.get(".type").toString(); // 计数+1 typeCountMap.put(type, typeCountMap.getOrDefault(type, 0) + 1); } // 遍历对象所有value,继续递归 for (Object value : jsonObj.values()) { traverseNode(value); } } // 节点是JSONArray类型(即[]包裹的数组) else if (node instanceof Iterable) { Iterable<Object> jsonArr = (Iterable<Object>) node; // 遍历数组所有元素,继续递归 for (Object item : jsonArr) { traverseNode(item); } } // 其他基本类型(字符串、数字等)不需要处理 } }
关键改动说明
- 去掉了将value转字符串存储的逻辑,保留JSON原始的对象/数组类型,避免丢失结构信息
- 新增递归遍历方法,自动识别当前节点是对象还是数组,分别执行遍历逻辑,支持任意层级的嵌套结构
- 用
typeCountMap存储所有.type的出现次数,后续通过switch语句可直接针对不同类型做自定义处理
运行效果
你给出的示例数据运行后会输出:
-------------------------------------------------------------------- Key is: raindrop, Value is : {".type":"uri",".value":"http:blahblahblah.info"} Key is: apex, Value is : [{".type":"inet4",".value":"3.3.3.3"},{".type":"inet4",".value":"3.3.3.3"},{".type":"inet4",".value":"3.3.3.3"},{".type":"inet4",".value":"3.3.3.3"},{".type":"inet4",".value":"3.3.3.3"}] Key is: coffee, Value is : [{".type":"bigdec",".value":"2626262626.234234234234234"}] -------------------------------------------------------------------- .type字段统计结果: URI类型出现次数:1 IPV4地址类型出现次数:5 高精度数字类型出现次数:1
内容的提问来源于stack exchange,提问作者SRSLOL
相关产品推荐
相关产品推荐

