0

我正在使用 Jackson 来处理 Hadoop 中以块形式出现的 JSON。这意味着,它们是被分割成块的大文件(在我的问题中是 128M,但这并不重要)。出于效率原因,我需要它是流式传输的(不可能在内存中构建整个树)。

我正在使用 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 进行细粒度(标题并移动到“记录”标记),然后我使用 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);

现在,假设我有一个包含两个输入分割的文件(即“记录”中有很多元素)。有效的 JSON 从第一次拆分开始,我读取并保留标题(每条记录都需要它,在本例中为“日期”字段)。

拆分将剪切 Records 数组中的任何位置。所以让我们假设我得到第二次这样的分裂:

                ... 
                },
                {"TSSName":"ZZZ", 
                ... 
                },
                {"TSSName":"ZZZ2", 
                ... 
                }
            ] } ] } } ]

我可以在开始解析之前进行检查,以将 InputStream (FSDataInputStream) 移动到记录的开头 ("{" ),其中包含下一个 "TSSNAME"(这可以完成)。在开始时丢弃尾随的“垃圾”很好。所以我们得到了这个:

                {"TSSName":"ZZZ", 
                ... 
                },
                {"TSSName":"ZZZ2", 
                ... 
                },
                ...
            ] } ] } } ]

然后我将它处理到上面看到的 JsonParser/ObjectMapper 对。第一个对象“ZZZ”读取正常。但是对于下一个“ZZZ2”,它打破了:JSONParser 抱怨 JSON 格式错误。它遇到一个“,”不在数组中。所以它失败了。然后我无法继续阅读我的记录。

如何解决这个问题,所以我仍然可以从第二个(和第 n 个)拆分中读取我的记录?如何让解析器忽略逗号上的这些错误,或者让解析器提前知道它正在读取数组的内容?

4

1 回答 1

0

似乎只要捕获异常就可以了:解析器继续运行,并且能够继续通过 ObjectMapper 读取对象。

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

于 2014-12-12T13:00:22.623 回答