我有一个方法,它接收JSON格式的InputStream数据。使用Jackson的ObjectMapper,我能够将InputStream转换为可以编辑的JsonNode,如下所示:
JsonNode revisions = mapper.readTree(data);
从那里,我可以迭代每个元素并进行更改。不过,在这样做的过程中,我将所有元素存储在一个列表中,然后将该列表转换为Stream。我更喜欢从InputStream一次对每个元素进行一个操作,这样我就不必将其全部存储在内存中。
这是我的:
public Stream<Revision> jsonToRevisionObjects(InputStream allData) throws IOException {
// convert the InputStream to a JsonNode
JsonNode revisions = mapper.readTree(allData);
List<Revision> newRevisions = new ArrayList<>();
for (JsonNode revision : revisions.get("results")) {
// create Revision objects and add them to newRevisions
}
return newRevisions.stream();
}
这基本上违背了使用Stream的意义,因为我将所有新的Revision对象存储到内存中。相反,我希望一次读取一个元素,并在加载下一个元素之前将其发送到流中。有办法做到这一点吗?根据周围的代码,输入参数将始终是InputStream(存在问题),返回类型将始终是Stream。
如果我能够将InputStream转换为Stream并执行以下操作,这可能是可能的:
return allDataStream.map(rev -> {
// create Revision object
});
但如果有可能的话,我不知道如何达到这一点。
要使用流式读取,必须直接使用JsonParser
,或将其传递给ObjectMapper
/ObjectReader
。如果是这样的话,如果你想的话,你可以把子树读成JsonNode
。
从InputStream
构建JsonParser
很简单:
JsonParser p=mapper.getFactory().createParser(inputStream);
但是在此之后的操作变化;您可以直接从JsonParser
读取令牌流,也可以要求ObjectMapper
或ObjectReader
从流中读取下一个"值"。然后JSON数据的结构很重要;如果您想避免读取所有内容,您可能需要提前解析器的流(nextToken()
)。