2014-12-04 71 views
0

我正在使用杰克逊来处理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个)分裂读我的记录?我怎样才能让解析器忽略逗号上的这些错误,或者让解析器事先知道它正在读取数组的内容?

回答

0

看起来好像只是捕捉异常:解析器继续运行,并且能够通过ObjectMapper继续读取对象。

我不太喜欢它 - 我想要一个解析器无法在非标准或甚至不良JSON上抛出异常的选项。所以我不知道这是否完全回答了这个问题,但我希望它有帮助。