You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 02:45:03