我需要摄取大型JSON文件,其记录可能跨越多行(而不是文件)(完全取决于数据提供者如何编写它)。
Elephant-Bird假定LZO压缩,我知道数据提供者不会这样做。
Dzone文章http://java.dzone.com/articles/hadoop-practice假设JSON记录将在同一行。
任何想法,除了压缩JSON ...文件都将是巨大的...如何正确分割文件,使JSON不会破坏。
编辑:行,而不是文件
答案 0 :(得分: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反序列化器(或者只是将多行文本传递给您的映射器。
答案 1 :(得分:1)
分割和解析多行JSON数据的最佳方法是扩展NLineInputFormat类并定义自己构成InputSplit的概念。 [例如:1000个JSON记录可能构成1个分割]
然后,您需要扩展LineRecordReader类并定义自己构成1行的概念[在本例中为1记录]。
通过这种方式,您可以获得定义明确的分割,每个分割包含N' N' N' N' JSON记录,然后可以使用相同的LineRecordReader读取,每个map任务将一次接收一条记录。
Charles Menguy对How does Hadoop process records split across block boundaries?的回复很好地解释了这种方法的细微差别。
对于此类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