如何使用Gson Streaming API解析含多个顶层对象的JSON?
Gson Streaming API 遍历多元素顶层对象解决方案
问题核心是处理顶层对象内的子元素时,没有正确维护JSON阅读器的上下文,导致遍历提前终止。现有代码的逻辑没有完整消费所有令牌,或是未在处理完子对象/数组后正确调用endObject()/endArray(),使得阅读器位置错乱,hasNext()提前返回false,无法处理后续的results数组。
以下是针对你的JSON结构的修正代码:
JsonReader reader = new JsonReader(new StringReader(yourJsonContent)); try { // 启动顶层对象遍历 reader.beginObject(); while (reader.hasNext()) { JsonToken token = reader.peek(); // 顶层对象的每个元素都是键值对,先处理NAME令牌 if (token == JsonToken.NAME) { String key = reader.nextName(); switch (key) { case "meta": // 处理meta子对象 reader.beginObject(); while (reader.hasNext()) { String metaKey = reader.nextName(); switch (metaKey) { case "disclaimer": String disclaimer = reader.nextString(); // 这里添加disclaimer的业务处理逻辑 break; case "terms": String terms = reader.nextString(); // 处理terms break; case "license": String license = reader.nextString(); // 处理license break; case "last_updated": String lastUpdated = reader.nextString(); // 处理last_updated break; case "totals": // 处理totals子对象 reader.beginObject(); while (reader.hasNext()) { String totalKey = reader.nextName(); switch (totalKey) { case "skip": int skip = reader.nextInt(); // 处理skip break; case "limit": int limit = reader.nextInt(); // 处理limit break; case "total": int total = reader.nextInt(); // 处理total break; default: // 跳过未知键,避免令牌阻塞 reader.skipValue(); break; } } reader.endObject(); break; default: reader.skipValue(); break; } } // 结束meta对象遍历,回到顶层上下文 reader.endObject(); break; case "results": // 处理results数组 reader.beginArray(); while (reader.hasNext()) { reader.beginObject(); while (reader.hasNext()) { String resultKey = reader.nextName(); if (resultKey.equals("result")) { String value = reader.nextString(); // 处理单个result值,比如打印或存入集合 System.out.println("获取结果值:" + value); } else { reader.skipValue(); } } reader.endObject(); } // 结束数组遍历,回到顶层上下文 reader.endArray(); break; default: reader.skipValue(); break; } } else { // 遇到非预期令牌,直接跳过 reader.skipValue(); } } // 结束顶层对象遍历 reader.endObject(); } catch (IOException e) { e.printStackTrace(); } finally { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } }
关键注意事项
- 每调用一次
beginObject()/beginArray(),必须对应调用endObject()/endArray(),保证阅读器回到上层JSON结构的上下文 - 遇到未知键时,必须调用
skipValue()跳过,否则阅读器会停留在该位置,导致后续遍历异常 - 处理每个键值对时,先通过
nextName()获取键名,再根据值的类型(对象、数组、基本类型)进行对应处理,确保所有令牌都被正确消费
内容的提问来源于stack exchange,提问作者NoazDad
相关产品推荐
相关产品推荐

