使用Jackson流式解析大体积HttpResponse JSON提取data字段返回流方案问询
解决方案
你当前使用的Jackson流式API本身就支持超大JSON的增量处理,不需要额外引入其他依赖库。你现有代码中getValueAsString()会将整个data字段的内容一次性加载为字符串,只需要调整为边解析边写入HttpServletResponse的输出流即可,全程不会全量加载响应内容到内存。
实现代码
import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import java.io.InputStream; import java.io.OutputStream; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import javax.servlet.http.HttpServletResponse; public void streamFilteredData(HttpServletResponse httpServletResponse) throws Exception { // 构造上游请求客户端和请求对象,此处替换为你自己的实现 HttpClient client = HttpClient.newHttpClient(); HttpRequest httpRequest = buildYourRequest(); // 上游响应以流的形式接收,不提前加载全量内容 HttpResponse<InputStream> upstreamResp = client.send(httpRequest, HttpResponse.BodyHandlers.ofInputStream()); // 配置下游响应头,可根据实际业务调整 httpServletResponse.setContentType("application/json"); httpServletResponse.setCharacterEncoding("UTF-8"); JsonFactory jsonFactory = new JsonFactory(); // 所有流通过try-with-resources自动关闭,避免资源泄漏 try ( InputStream upstreamInput = upstreamResp.body(); JsonParser parser = jsonFactory.createParser(upstreamInput); OutputStream downstreamOutput = httpServletResponse.getOutputStream(); JsonGenerator generator = jsonFactory.createGenerator(downstreamOutput) ) { // 遍历根节点的字段 while (parser.nextToken() != JsonToken.END_OBJECT) { String fieldName = parser.getCurrentName(); if ("data".equals(fieldName)) { // 定位到data字段的内容起始位置 parser.nextToken(); // 核心方法:流式拷贝当前节点的所有内容到输出流,不会全量加载到内存 generator.copyCurrentStructure(parser); // 已拿到目标字段,直接退出解析,无需处理后续内容 break; } else { // 非目标字段直接跳过解析,提升性能 parser.skipChildren(); } } generator.flush(); } }
关键说明
generator.copyCurrentStructure(parser)是核心实现,该方法会从JsonParser的当前位置开始,逐段读取上游输入流的内容,同步写入下游输出流,内存占用始终维持在KB级别,哪怕data字段内容超过百万行也不会出现OOM问题。- 该方法支持任意类型的
data字段:字符串、数字、对象、数组都可以正常流式输出,无需额外适配。 - 如果你需要对
data内部的内容做二次过滤,只需要在找到data字段后手动遍历parser的Token,按需写入generator即可,依然可以保持流式处理的低内存特性。
内容的提问来源于stack exchange,提问作者Przemek Lewandowski
相关产品推荐
相关产品推荐

