簡體   English   中英

使用Apache Spark讀取Json文件

[英]Reading Json file using Apache Spark

我正在嘗試使用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

如果必須閱讀此JSON,則需要將JSON格式化為一行。 這是多行JSON,因此無法正確讀取和加載(一個對象一行)

引用JSON API:

加載JSON文件(每行一個對象),並將結果作為DataFrame返回。

{"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>

您也應該能夠從代碼中完成此操作

只需確保您的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

嘗試:

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

該線程有點舊,我只想詳細說明@ user6022341的建議。 我最終使用它是我的一個項目:

要處理多行json文件,如果文件是一個大的json對象,則WholeTextFiles(String path)轉換是spark中的唯一解決方案。 此轉換將整個文件內容作為字符串加載。 因此,如果在hdfs:// a-hdfs-path目錄中,則有兩個文件,即part-00000和part-00001。 調用sparkContext.wholeTextFiles(“ hdfs:// a-hdfs-path”)將導致Spark返回JavaPairRDD,該JavaPairRDD的鍵為文件名,值為文件的內容。 這可能不是最佳解決方案,並且可能會影響較大文件的性能。

但是,如果多行json文件將多個json對象分成多行,那么您可能可以使用hadoop.Configuration, 此處顯示一些示例代碼。 我還沒有自己測試過。

如果必須讀取多行csv文件,則可以使用Spark 2.2執行此操作

 spark.read.csv(file, multiLine=True) 

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

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

希望這可以幫助其他人尋找類似的信息。

在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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM