Jackson JSON Streaming API:直接将整个对象读取到String

时间:2013-08-05 04:17:11

标签: java json string streaming jackson

我正在尝试按对象流式传输JSON数组,但我需要将其作为原始JSON字符串导入。

给出一系列输入:

[
 {"object":1},
 {"object":2},
 ...
 {"object":n}
]

我试图遍历字符串:

{"object":1}
{"object":2}
...
{"object":n}

我可以使用流API来导航结构,以验证我遇到了一个对象,以及所有这些,但我认为我收回S​​tring的方式是理想的。

目前:

//[...]
//we have read a START_OBJECT token
JsonNode node = parser.readValueAsTree();
String jsonString = anObjectMapper.writeValueAsString(node);
//as opposed to  String jsonString = node.toString() ;
//[...]

我想整个JsonNode结构的构建涉及一堆开销,如果我只是重新编译,这是没有意义的,所以我正在寻找更好的解决方案。根据这一点,这将是理想的:

//[...]
//we have read a START_OBJECT token
String jsonString = parser.readValueAsString()
//or parser.skipChildrenAsString()
//[...]

对象显然不像

那么简单
{"object":1}

这就是为什么我不打算浪费时间做无意义的节点建设。可能有一些理想的方法,包括将内容映射到对象并使用它,但我不能处于能够做到这一点的位置。我需要原始JSON字符串,一次一个对象,以使用现有代码。

任何建议或意见表示赞赏。谢谢!

编辑: parser.getText()将当前标记作为文本返回(例如START_OBJECT - >“{”),但不返回对象的其余部分。

Edit2:使用Streaming API的动机是逐个缓冲对象。实际的json文件可能非常大,每个对象在使用后都可以丢弃,所以我只需要迭代。

1 个答案:

答案 0 :(得分:4)

没有办法避免JSON标记化(否则解析器不会知道对象的开始和结束位置等)​​,因此它总是涉及某种程度的解析和生成。

但是你可以通过读取值TokenBuffer来略微减少开销 - 这是Jackson的内部类型,具有最低的内存/性能开销(并且在需要缓冲的时候在内部使用):

TokenBuffer buf = parser.readValueAs(TokenBuffer.class);
// write straight from buffer if you have JsonGenerator
jgen.writeObject(buf);
// or, if you must, convert to byte[] or String
byte[] stuff = mapper.writeValueAsBytes();

我们可以做得更好但是:如果您可以为输出创建JsonGenerator,只需使用JsonGenerator.copyCurrentStructure(JsonParser);

jgen.copyCurrentStructure(jp); // points to END_OBJECT after copy

这将避免所有对象分配;虽然它需要解码JSON,然后以JSON编码,它会相当高效。 事实上你甚至可以在转码中使用它 - 在杰克逊支持的任何格式之间读取JSON,编写XML / Smile / CSV / YAML / Avro。