如何在Java 8中遍历包含JSONObject与JSONArray的JSONArray
解决混合JSONObject和JSONArray的JSONArray遍历问题(Java 8实现)
首先,你之前遇到的MismatchedInputException是因为顶层JSON数组里同时包含单个对象和子数组,直接用Jackson把整个数组反序列化成List<PojoClass>肯定行不通——Jackson没法自动识别这种混合结构,它期望所有元素都是PojoClass对应的对象,结果遇到数组节点就报错了。
你的普通for循环思路是对的,但有个小bug:内层循环里你错误用了jsonArrayList.optJSONObject(j),应该是jsonArrayInner.optJSONObject(j),不然会取到顶层数组的元素而非子数组的。不过既然要Java 8的实现,我们可以用流式API结合Jackson的JsonNode来更优雅地解决这个问题。
前提准备
首先确保你的PojoClass和JSON结构完全对应,比如嵌套的Value1_tim需要一个内部类或者单独的类:
public class PojoClass { private String Key1; private String Key2; private String Key3; private TimeValue Value1_tim; // 生成getter、setter、无参构造器 public static class TimeValue { private int amVal; private String pmVal; // 生成getter、setter、无参构造器 } }
Java 8流式实现代码
我们用Jackson的JsonNode来灵活处理混合类型的JSON节点,配合流式API来遍历和收集结果:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; // 初始化ObjectMapper(建议全局单例) ObjectMapper objectMapper = new ObjectMapper(); // 把JSON响应解析成顶层的ArrayNode ArrayNode topLevelArray = (ArrayNode) objectMapper.readTree(jsonResponse); // 流式遍历并收集所有PojoClass实例 List<PojoClass> pojoClassList = topLevelArray.stream() .flatMap(node -> { if (node.isObject()) { // 单个JSONObject节点:转成单元素流 try { return Stream.of(objectMapper.treeToValue(node, PojoClass.class)); } catch (Exception e) { throw new RuntimeException("反序列化单个对象失败", e); } } else if (node.isArray()) { // JSONArray节点:遍历内部的每个对象节点,转成流 return ((ArrayNode) node).stream() .filter(JsonNode::isObject) // 确保只处理对象节点,避免非对象类型 .map(innerNode -> { try { return objectMapper.treeToValue(innerNode, PojoClass.class); } catch (Exception e) { throw new RuntimeException("反序列化子数组对象失败", e); } }); } else { // 处理其他非对象/数组的节点(比如字符串、数字),这里直接忽略 return Stream.empty(); } }) .collect(Collectors.toList());
代码解释
- 用
readTree解析JSON:这个方法会把JSON转换成JsonNode树结构,能灵活处理各种JSON类型(对象、数组、基本类型),比org.json的JSONArray更适合和Jackson配合使用。 flatMap合并流:flatMap的作用是把每个节点对应的流合并成一个大的流——单个对象转成单元素流,子数组转成内部对象的流,最终所有PojoClass实例都在同一个流里。treeToValue高效反序列化:直接把JsonNode转换成PojoClass,比先转成字符串再反序列化更高效,也避免了字符串转换的额外开销。- 异常处理:这里用
RuntimeException包裹反序列化异常,实际项目中你可以根据需求自定义异常类型,或者添加更细致的错误处理逻辑。
为什么不用org.json的API?
org.json的JSONArray和JSONObject更偏向于底层的JSON操作,而Jackson的JsonNode和ObjectMapper结合得更紧密,处理混合类型的JSON结构时代码更简洁,也更符合Java 8的流式编程风格。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

