我正在使用杰克逊来处理JSON在Hadoop中的块。这意味着,它们是大块文件(在我的问题中它是128M但它并不重要)。 出于效率的原因,我需要它流式传输(不可能在内存中构建整个树)。杰克逊jsonparser重新启动解析破碎的JSON
我正在使用JsonParser和ObjectMapper的混合来读取我的输入。 目前,我正在使用不可拆分的自定义InputFormat,因此我可以阅读我的整个JSON。
的(有效)JSON的结构是这样的:
[ { "Rep":
{
"date":"2013-07-26 00:00:00",
"TBook":
[
{
"TBookC":"ABCD",
"Records":
[
{"TSSName":"AAA",
...
},
{"TSSName":"AAB",
...
},
{"TSSName":"ZZZ",
...
}
] } ] } } ]
我想在我的RecordReader阅读的记录是“记录”元素中的元素。 “...”意味着那里有更多的信息,这符合我的记录。 如果我只有一个拆分,那完全没有问题。 我使用JsonParser获得细粒度(标题并移动到“Records”标记),然后使用ObjectMapper和JsonParser将对象读取为记录。有关详情:
configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false);
MappingJsonFactory factory = new MappingJsonFactory();
mapper = new ObjectMapper(factory);
mapper.configure(Feature.FAIL_ON_UNKNOWN_PROPERTIES,false);
mapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS,false);
parser = factory.createJsonParser(iStream);
mapper.readValue(parser, JsonNode.class);
现在,让我们想象我有两个inputsplits文件(即有很多的元素在“史记”)。 有效的JSON从第一次分割开始,并且我读取并保存了标题(每个记录都需要这些标题,在本例中为“日期”字段)。
分割会切割记录数组中的任何位置。因此,让我们假设我有第二次分裂是这样的:
...
},
{"TSSName":"ZZZ",
...
},
{"TSSName":"ZZZ2",
...
}
] } ] } } ]
我可以检查之前,我开始分析,以InputStream的(FSDataInputStream)移动到下一个“TSSNAME”记录的开始(“{”)在其中(并且这样做确定)。在开始时丢弃尾随的“垃圾”是很好的。因此,我们得到这样的:
{"TSSName":"ZZZ",
...
},
{"TSSName":"ZZZ2",
...
},
...
] } ] } } ]
然后我把它处理到JsonParser/ObjectMapper对上面看到的。 第一个对象“ZZZ”被读取OK。 但是对于下一个“ZZZ2”,它打破了:JSONParser关于格式错误的JSON的投诉。它遇到一个“,”不在数组中。所以它失败了。然后我不能继续阅读我的记录。
这个问题怎么解决,所以我仍然可以从第二个(和第n个)分裂读我的记录?我怎样才能让解析器忽略逗号上的这些错误,或者让解析器事先知道它正在读取数组的内容?