pyspark:将schemaRDD保存为json文件

时间:2014-11-04 14:11:32

标签: python json apache-spark

我正在寻找一种方法将数据从Apache Spark导出到JSON格式的各种其他工具。我认为必须有一种非常简单的方法来做到这一点。

示例:我有以下JSON文件'jfile.json':

{"key":value_a1, "key2":value_b1},
{"key":value_a2, "key2":value_b2},
{...}

其中文件的每一行都是JSON对象。这些文件可以通过

轻松读入PySpark
jsonRDD = jsonFile('jfile.json')

然后看起来像(通过调用jsonRDD.collect()):

[Row(key=value_a1, key2=value_b1),Row(key=value_a2, key2=value_b2)]

现在我想将这些类型的文件保存回纯JSON文件。

我在Spark用户列表中找到了这个条目:

http://apache-spark-user-list.1001560.n3.nabble.com/Updating-exising-JSON-files-td12211.html

声称使用

RDD.saveAsTextFile(jsonRDD) 

执行此操作后,文本文件看起来像

Row(key=value_a1, key2=value_b1)
Row(key=value_a2, key2=value_b2)

,即jsonRDD刚刚写入文件。在阅读Spark用户列表条目后,我本来期望一种“自动”转换回JSON格式。我的目标是在开头提到一个看起来像'jfile.json'的文件。

我错过了一个非常明显的简单方法吗?

我阅读http://spark.apache.org/docs/latest/programming-guide.html,搜索谷歌,用户列表和堆栈溢出以获得答案,但几乎所有答案都涉及阅读和解析JSON到Spark。我甚至买了“学习星火”这本书,但那里的例子(第71页)只是导致了与上面相同的输出文件。

有人可以帮我吗?我觉得我在这里只缺少一个小链接

提前干杯谢谢!

3 个答案:

答案 0 :(得分:5)

您可以使用方法toJson(),它允许您将SchemaRDD转换为JSON文档的MappedRDD。

https://spark.apache.org/docs/latest/api/python/pyspark.sql.html?highlight=tojson#pyspark.sql.SchemaRDD.toJSON

答案 1 :(得分:1)

我看不出一个简单的方法。一种解决方案是将SchemaRDD的每个元素转换为String,最后得到RDD[String],其中每个元素都为该行格式化为JSON。因此,您需要编写自己的JSON序列化程序。这很容易。它可能不是超快但它应该并行工作,并且您已经知道如何将RDD保存到文本文件中。

关键的见解是,您可以通过调用SchemaRDD方法从schema中获取模式的表示。然后,地图递送给您的每个Row需要递归遍历并与架构一起遍历。这实际上是针对平面JSON的串联列表遍历,但您可能还需要考虑嵌套的JSON。

剩下的只是Python的一个小问题,我不会说,但我确实有这个working in Scala,以防它帮助你。 Scala代码密集的部分实际上并不依赖于深入的Spark知识,所以如果你能理解基本的递归并且知道Python,那么你应该能够使它工作。您的大部分工作是弄清楚如何在Python API中使用pyspark.sql.Rowpyspark.sql.StructType

提醒一句:我很确定我的代码在缺少值的情况下还不起作用 - formatItem方法需要处理null元素。

修改:在 Spark 1.2.0 中,toJSON方法已引入SchemaRDD,使其成为很多更简单的问题 - 请参阅@jegordon的答案。

答案 2 :(得分:0)

我一直在SQL控制台中直接在Spark SQL中使用org.apache.spark.sql.json。不是最有效的方式,它可能被视为黑客,但它完成了工作。

CREATE TABLE jsonTable (
    key STRING,
    value STRING
)
USING org.apache.spark.sql.json
OPTIONS (
    PATH "destination/path"
);

创建表后,从已注册的临时表或任何其他表中插入数据

INSERT OVERWRITE TABLE jsonTable
SELECT * FROM tempTable;

注意:似乎这是启动一个配置单元映射,减少了在提供的路径下创建多个文件部分的作业。预期执行缓慢

注意:创建表时提供​​的路径位于hdfs,而不是本地文件系统。

注意:我没有尝试使用SQLContext.sql将其嵌入到脚本中,但它可能是可行的

注意:从表中选择jsonTable可能会因序列化而失败