使用Apache Spark读取Json文件

时间:2016-10-24 07:03:03

标签: java json hadoop apache-spark apache-spark-2.0

我正在尝试使用Spark v2.0.0读取Json文件。如果简单的数据代码工作得很好。如果数据有点复杂,当我打印df.show()时数据显示不正确。

这是我的代码:

SparkSession session = SparkSession.builder().master("local").appName("jsonreader").getOrCreate();
Dataset<Row> list = session.read().json("/Users/hadoop/Desktop/sample.json");
list.show();

以下是我的示例数据:

{
    "glossary": {
        "title": "example glossary",
        "GlossDiv": {
            "title": "S",
            "GlossList": {
                "GlossEntry": {
                    "ID": "SGML",
                    "SortAs": "SGML",
                    "GlossTerm": "Standard Generalized Markup Language",
                    "Acronym": "SGML",
                    "Abbrev": "ISO 8879:1986",
                    "GlossDef": {
                        "para": "A meta-markup language, used to create markup languages such as DocBook.",
                        "GlossSeeAlso": ["GML", "XML"]
                    },
                    "GlossSee": "markup"
                }
            }
        }
    }
}

我的输出就像:

+--------------------+
|     _corrupt_record|
+--------------------+
|                   {|
|       "glossary": {|
|        "title": ...|
|           "GlossDiv": {|
|            "titl...|
|               "GlossList": {|
|                "...|
|                 ...|
|                   "SortAs": "S...|
|                   "GlossTerm":...|
|                   "Acronym": "...|
|                   "Abbrev": "I...|
|                   "GlossDef": {|
|                 ...|
|                       "GlossSeeAl...|
|                 ...|
|                   "GlossSee": ...|
|                   }|
|                   }|
|                   }|
+--------------------+
only showing top 20 rows

5 个答案:

答案 0 :(得分:6)

如果必须阅读此JSON,则需要将JSON格式化为一行。这是一个多行JSON,因此无法正确读取和加载(One Object one Row)

引用JSON API:

  

加载JSON文件(每行一个对象)并将结果作为a返回   数据帧。

{"glossary":{"title":"example glossary","GlossDiv":{"title":"S","GlossList":{"GlossEntry":{"ID":"SGML","SortAs":"SGML","GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986","GlossDef":{"para":"A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso":["GML","XML"]},"GlossSee":"markup"}}}}}

我只是在shell上尝试过它,它应该以相同的方式从代码中工作(当我读取多行JSON时,我有同样的损坏记录错误)

scala> val df = spark.read.json("C:/DevelopmentTools/data.json")
df: org.apache.spark.sql.DataFrame = [glossary: struct<GlossDiv: struct<GlossList: struct<GlossEntry: struct<Abbrev: string, Acronym: string ... 5 more fields>>, title: string>, title: string>]

scala>

编辑:

您可以使用任何操作从该数据框中获取值,例如

scala> df.select(df("glossary.GlossDiv.GlossList.GlossEntry.GlossTerm")).show()
+--------------------+
|           GlossTerm|
+--------------------+
|Standard Generali...|
+--------------------+


scala>

你也应该能够从你的代码中做到这一点

答案 1 :(得分:3)

只要确保你的json在一行中你正在读取嵌套的json所以,如果你已经这样做了,你就成功加载了json你以错误的方式显示它的嵌套json所以你不能直接显示,就像你想要的一样您可以将GlossDiv的标题数据显示如下

SparkSession session = SparkSession.builder().master("local").appName("jsonreader").getOrCreate();
Dataset<Row> list = session.read().json("/Users/hadoop/Desktop/sample.json");
list.select("glossary.GlossDiv.title") .show

答案 2 :(得分:0)

尝试:

session.read().json(session.sparkContext.wholeTextFiles("..."));

答案 3 :(得分:0)

这个帖子有点旧,我想详细说明@ user6022341建议的内容。我最终使用了我的一个项目:

要处理多行json文件,如果文件是一个大的json对象,则wholeTextFiles(String path)转换是spark中唯一的解决方案。此转换将整个文件内容作为字符串加载。因此,如果在hdfs:// a-hdfs-path目录中,您有两个文件,即part-00000和part-00001。调用sparkContext.wholeTextFiles(&#34; hdfs:// a-hdfs-path&#34;)将导致Spark返回一个JavaPairRDD,其密钥作为文件名和值作为文件的内容。这可能不是最佳解决方案,可能会影响较大文件的性能。

但是如果多行json文件有多个json对象分成多行,那么你可以使用hadoop.Configuration,显示一些示例代码here。我自己还没有对此进行测试。

如果您必须阅读多行csv文件,则可以使用Spark 2.2执行此操作

&#13;
&#13;
spark.read.csv(file, multiLine=True)
&#13;
&#13;
&#13;

https://issues.apache.org/jira/browse/SPARK-19610

https://issues.apache.org/jira/browse/SPARK-20980

希望这有助于其他人寻找类似的信息。

答案 4 :(得分:0)

在Spark中使用Java读取JSON文件的另一种方式与上述类似:

SparkSession spark = SparkSession.builder().appName("ProcessJSONData")
                        .master("local").getOrCreate();

String path = "C:/XX/XX/myData.json";

// Encoders are created for Java bean class
Encoder<FruitJson> fruitEncoder = Encoders.bean(FruitJson.class);

Dataset<FruitJson> fruitDS = spark.read().json(path).as(fruitEncoder);

fruitDS.show();