Gson Streaming API解析非法JSON提前终止无法读取完整文档问题
问题根因
Gson 流式API的JsonReader即使开启宽松模式,默认遇到解析异常也会直接抛出MalformedJsonException并终止后续流读取,你遇到的空对象后提前停止,本质是读取完空对象的闭合}后,后续读取操作触发的非法格式异常没有被捕获,直接终止了整个解析流程,和空对象本身无关。
解决方案
1. 基础配置修正
首先确保开启完整宽松校验,允许未转义双引号、尾随逗号等常见非法格式:
JsonReader reader = new JsonReader(new InputStreamReader(yourInputStream, StandardCharsets.UTF_8)); reader.setLenient(true);
2. 逐Token手动解析+局部异常捕获
不要直接用fromJson做对象自动绑定,完全手动遍历JSON Token,每一步解析都做局部异常捕获,只跳过当前非法片段,不终止整个解析流程:
try { reader.beginObject(); // 顶层对象循环遍历 while (reader.hasNext()) { try { String fieldName = reader.nextName(); JsonToken currentToken = reader.peek(); // 按Token类型处理对应值,空对象会正常识别为BEGIN_OBJECT + END_OBJECT if (currentToken == JsonToken.BEGIN_OBJECT) { reader.beginObject(); // 内部对象循环 while (reader.hasNext()) { try { String innerField = reader.nextName(); // 内部字段处理逻辑,异常只捕获当前字段 reader.skipValue(); } catch (MalformedJsonException e) { // 跳过当前非法内部字段,继续下一个 skipMalformedSegment(reader); } } reader.endObject(); } else if (currentToken == JsonToken.STRING) { String value = reader.nextString(); // 字符串类型处理逻辑 } else { // 其他类型统一跳过,按需调整处理逻辑 reader.skipValue(); } } catch (MalformedJsonException e) { // 顶层字段解析异常,跳过当前非法段,继续下一个字段 skipMalformedSegment(reader); } } reader.endObject(); } catch (IOException e) { // 处理流层面的最终异常 } finally { try { reader.close(); } catch (IOException ignore) {} }
3. 实现非法片段跳过逻辑
异常触发后,跳过当前非法字符直到遇到合法JSON分隔符,恢复解析状态:
private void skipMalformedSegment(JsonReader reader) throws IOException { // 简单实现,循环尝试跳过值直到遇到合法分隔符,无需反射 while (true) { try { JsonToken token = reader.peek(); if (token == JsonToken.COMMA || token == JsonToken.END_OBJECT || token == JsonToken.END_ARRAY) { break; } reader.skipValue(); } catch (MalformedJsonException e) { // 跳过单个非法字符 reader.skipValue(); } } }
4. 空对象兼容注意事项
处理完空对象的endObject()后,必须继续判断父层级的hasNext()状态,不要在读取完空对象后直接退出循环,避免提前终止解析。
内容的提问来源于stack exchange,提问作者Subhendu Mahanta
相关产品推荐
相关产品推荐

