JSON对象跨越多行,如何在Hadoop中拆分输入

7
我需要导入大型JSON文件,其中的记录可能跨越多行(而不是文件)(这完全取决于数据提供者的编写方式)。
Elephant-Bird假设使用LZO压缩,但我知道数据提供者不会这样做。
Dzone文章http://java.dzone.com/articles/hadoop-practice假设JSON记录在同一行上。
有什么想法,除了压缩JSON之外...文件会很大...如何正确地拆分文件,使JSON不会中断。
编辑:行而不是文件

如果您想要进行“验证”(即建立一个上下文,让您知道何时语法上完成了JSON字符串的解析,而无需将整个字符串加载到内存中),则可以查看基于事件的解析器(类似于SAX在XML中所做的)。此答案https://dev59.com/PnRB5IYBdhLWcg3w-8Lo#823632列出了一些。 - Tomalak
数据提供者将准备以JSON格式加载数据(不要问我为什么是JSON,我想他们已经在他们的端口设置了该源)。某些专有系统将文件放入HDFS以通过M / R过程运行。想法是当读取输入文件时,我可以可靠地拆分它,使得顶级JSON对象不会被破坏。问题是我无法控制文件本身,因此可能会向我倾销跨越多行的顶级对象。 - Maz
Chukwa应该有一个JSONInputFormat,但我不知道它是否可以读取多行。 - Thomas Jungblut
我的建议是通过一个简单的流解析器(类似于这篇文章中使用的Jackson,参见第2点)来处理它。解析器只需要做一件事情:处理嵌套深度,观察正确的结束标记。这样你就知道JSON对象何时完成(并且,顺便说一句,它是否格式良好)。不过我不能为你创建这样的程序,所以这只是一个大致的想法。 - Tomalak
Chukwa有一个JSONLoader,但没有扩展JSON的InputFormat类。 - Maz
你还需要担心的一件事是,除非你自己实现了自定义分割,否则记录本身可能会被分割成多个映射器。 - Fakrudeen
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个空格和一个闭合括号。然后使用任何JSON反序列化器将其转换为Java对象(或者只需将多行文本传递给映射器即可)。


供应商的JSON格式非常简单。虽然我感谢您的回复并会将其收藏以备将来参考,但我最终决定假设它是一个没有深度的简单键值对(在这种情况下是这样)。我的愿望是通过为将来的JSON提供程序提供解决方案来“一次性搞定”...但在这种情况下,敏捷性胜过完美。 - Maz

1
您最好的方式是扩展NLineInputFormat类并定义自己的InputSplit概念来拆分和解析多行JSON数据。例如: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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接