5

我正在尝试使用 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
4

5 回答 5

7

如果您必须阅读此 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>

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

于 2016-10-24T07:17:40.450 回答
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
于 2016-10-24T08:04:23.383 回答
0

尝试:

session.read().json(session.sparkContext.wholeTextFiles("..."));
于 2016-10-24T08:38:11.160 回答
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();
于 2018-09-06T16:32:46.783 回答
0

这个帖子有点老了,我想详细说明@user6022341 的建议。我最终在我的项目之一中使用了它:

要处理多行 json 文件,wholeTextFiles(String path) 转换是 spark 中唯一的解决方案,如果文件是一个大的 json 对象。此转换会将整个文件内容作为字符串加载。因此,如果在 hdfs://a-hdfs-path 目录中有两个文件,即 part-00000 和 part-00001。调用 sparkContext.wholeTextFiles("hdfs://a-hdfs-path") 将导致 Spark 返回一个 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

希望这可以帮助其他寻找类似信息的人。

于 2017-08-25T03:37:03.013 回答