7

我需要摄取大型 JSON 文件,其记录可能跨越多行(不是文件)(完全取决于数据提供者的编写方式)。

Elephant-Bird 采用 LZO 压缩,我知道数据提供者不会这样做。

Dzone 文章http://java.dzone.com/articles/hadoop-practice假设 JSON 记录将位于同一行。

任何想法,除了压缩 JSON... 文件将是巨大的... 关于如何正确拆分文件以使 JSON 不会中断。

编辑:行,而不是文件

4

2 回答 2

2

缺少任何其他建议,并且取决于 JSON 的格式,您可能有一个选择。

正如 Dzone 文章中指出的那样,问题在于 JSON 没有结束元素,当您跳转到一个分割点时,您可以轻松找到它。

现在,如果您的输入 JSON 具有“漂亮”或标准格式,您可以在自定义输入格式实现中利用这一点。

例如,从 Dzone 示例中获取示例 JSON:

{
  "results" :
    [
      {
        "created_at" : "Thu, 29 Dec 2011 21:46:01 +0000",
        "from_user" : "grep_alex",
        "text" : "RT @kevinweil: After a lot of hard work by ..."
      },
      {
        "created_at" : "Mon, 26 Dec 2011 21:18:37 +0000",
        "from_user" : "grep_alex",
        "text" : "@miguno pull request has been merged, thanks again!"
      }
    ]
}

使用这种格式,您知道(希望?)每条新记录都从包含 6 个空格和一个左括号的行开始。记录以类似的格式结束 - 6 个空格和一个右括号。

所以你在这种情况下的逻辑:使用行,直到你找到一个有 6 个空格和一个左括号的行。然后缓冲内容,直到找到 6 个空格和一个右括号。然后使用您想要将其转换为 java 对象的任何 JSON 反序列化器(或者只是将多行文本传递给您的映射器。

于 2012-08-14T01:10:04.363 回答
1

拆分和解析多行 JSON 数据的最佳方法是扩展 NLineInputFormat 类并定义您自己的 InputSplit 构成概念。[例如:1000 条 JSON 记录可以构成 1 个拆分]

然后,您需要扩展 LineRecordReader 类并定义您自己的概念,即什么构成 1 行 [在本例中为 1 条记录]。

这样,您将获得定义明确的拆分,每个拆分都包含“N”个 JSON 记录,然后可以使用相同的 LineRecordReader 读取这些记录,并且您的每个地图任务将一次接收一条记录以进行处理。

Charles Menguy 对Hadoop 处理记录如何跨块边界拆分的回复?很好地解释了这种方法的细微差别。

有关 NLineInputFormat 的此类扩展示例,请查看http://hadooped.blogspot.com/2013/09/nlineinputformat-in-java-mapreduce-use.html

可以在此处找到类似的 Hadoop 多行 CSV 格式:https ://github.com/mvallebr/CSVInputFormat

更新:我在这里找到了适用于 Hadoop 的相关多行 JSON 输入格式: https ://github.com/Pivotal-Field-Engineering/pmr-common/blob/master/PivotalMRCommon/src/main/java/com/gopivotal/ mapreduce/lib/input/JsonInputFormat.java

于 2015-11-07T04:04:47.913 回答