【问题标题】:Reading Json file using Apache Spark使用 Apache Spark 读取 Json 文件
【发布时间】:2017-03-05 21:06:14
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

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

    引用 JSON API:

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

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

    您也应该可以通过您的代码来实现这一点

    【讨论】:

    • 感谢您的回复.. 当我尝试时,我得到了这个作为输出。+--------------------+ |词汇表| +--------------------+ |[[[[ISO 8879:1986...| +--------------------+
    • 这是预期的。添加了一个示例操作来显示评估/处理
    【解决方案2】:

    只要确保你的 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
    

    【讨论】:

      【解决方案3】:

      试试:

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

      【讨论】:

        【解决方案4】:

        这个帖子有点老了,我想详细说明@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,一些示例代码显示为here。我自己没有测试过。

        如果您必须读取多行 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

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            猜你喜欢
            • 2016-12-18
            • 1970-01-01
            • 1970-01-01
            • 2021-06-22
            • 2021-12-07
            • 1970-01-01
            • 2019-02-08
            • 1970-01-01
            • 2023-04-09
            相关资源
            最近更新 更多