如何流式处理JSON对象内的JSON数组?Gson大JSON解析求助
解决方案:流式解析外层对象内的超大JSON数组
你完全不需要折腾修改源JSON文件!你的问题核心是没正确处理JSON的外层对象结构——你的JSON根节点是一个对象(用{}包裹),而不是数组,所以直接调用beginArray()肯定会报错。另外还有个小细节:你的Message类字段First_Name和JSON里的FirstName命名不匹配,Gson会无法正确映射,这点也需要修正。
修正后的完整实现
首先调整Message类,保证字段名和JSON一致(或者用@SerializedName注解指定映射关系):
class Message { // 和JSON字段名完全一致,Gson可以自动映射 public String FirstName; public String Position; public String Worker; // 如果你不想改字段名,也可以用注解指定映射: // @SerializedName("FirstName") // public String First_Name; // public String Position; // public String Worker; }
然后是流式解析的核心代码:
InputStream inStream = null; JsonReader reader = null; Gson gson = new Gson(); try { inStream = new FileInputStream("C:\\Downloads\\largereportdata.json"); reader = new JsonReader(new InputStreamReader(inStream, StandardCharsets.UTF_8)); List<Message> messages = new ArrayList<>(); // 先处理外层的根对象 reader.beginObject(); while (reader.hasNext()) { String fieldName = reader.nextName(); // 定位到我们需要的Report_Entry数组字段 if ("Report_Entry".equals(fieldName)) { // 进入数组,开始流式遍历每个元素 reader.beginArray(); while (reader.hasNext()) { // 逐个解析数组中的单个对象,仅当前对象会占用内存 Message message = gson.fromJson(reader, Message.class); // 在这里处理单个message(比如入库、统计等) messages.add(message); } reader.endArray(); } else { // 如果外层还有其他无关字段,直接跳过,避免解析错误 reader.skipValue(); } } reader.endObject(); } catch (IOException e) { e.printStackTrace(); } finally { // 确保IO资源被正确关闭 try { if (reader != null) reader.close(); if (inStream != null) inStream.close(); } catch (IOException e) { e.printStackTrace(); } }
方案优势
- 无需修改源文件:全程直接读取原始JSON,避免了预处理文件的麻烦;
- 低内存占用:仅单个
Message对象会被加载到内存,即使JSON文件几个G也能轻松处理; - 鲁棒性强:如果外层对象还有其他无关字段,
skipValue()会自动跳过,不会触发解析错误。
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

