2016-04-29 39 views
0

我有一种方法接收JSON格式的InputStream数据。使用杰克逊的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(); 
} 

这实际上违背了即使使用流,因为我存储所有的新修订的对象到内存中的点。相反,我想一次读取一个元素,并在加载下一个元素之前将其发送到流中。有没有办法做到这一点?基于周围的代码,输入参数将始终是InputStream(存在问题),并且返回类型将始终为Stream。

,如果我能一个InputStream转换成流,这可能是可能的,请执行下列操作:

return allDataStream.map(rev -> { 
    // create Revision object 
     }); 

,但我不知道怎么去这一点,如果它是有可能的。

+0

我假设'allData'是一个JSON对象列表,是否正确?我想知道,在这种情况下,是否可以一次一个地读取每个对象,而不是整个列表 –

+0

是的,这是我想要做的。如果数据以流的形式传入(然后我可以使用map),这很容易,但我不确定该怎么做,因为它是以InputStream的形式输入的 – user2869231

+0

我发现了对类似问题的以下响应可能会有所帮助http://stackoverflow.com/a/31275144/3529744 –

回答

0

要使用流式读取,您必须直接使用JsonParser,或将其传递给ObjectMapper/ObjectReader。如果是这样,你可以阅读子树作为JsonNode如果你想。

为了构建JsonParserInputStream很简单:

JsonParser P = mapper.getFactory()createParser(的inputStream);

但在此之后的操作变化;您可以直接从JsonParser读取令牌流,或者请求ObjectMapperObjectReader从流中读取下一个“值”。然后JSON数据的结构很重要;如果您想避免读取所有内容,则可能需要提前解析器的流(nextToken())。

+0

嗯,这需要一些工作,但我会尝试一些事情。你知道是否有办法一次获得大块json?正如在..我有一个JSON对象的列表,并希望一次在该列表中获取一个完整的对象(所以我们假设3个键:值对)。我可以一次一个迭代地执行nextField和nextValue,但我宁愿只是在一次创建整个地图 – user2869231

+0

@ user2869231不太确定我在这里理解您的问题。Jackson必须解码底层JSON内容的部分内容才能知道是什么内容,并将其作为“JsonToken”流公开,并使用JsonParser.nextToken()和类似的方法遍历。有了这个,你可以做任何你想做的事情。在更高层次上,由于他们读取子树,所以'ObjectReader' /'ObjectMapper'的选择更加有限。 – StaxMan

相关问题