web-dev-qa-db-ja.com

Apacheを使用してJsonファイルを読み取る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
5
user6325753

このJSONを読み取る必要がある場合は、JSONを1行にフォーマットする必要があります。これは複数行のJSONであるため、正しく読み取られて読み込まれていません (One Object one Row)

JSON APIの引用:

JSONファイル(1行に1つのオブジェクト)をロードし、結果を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"}}}}}

シェルで試してみましたが、コードからも同じように機能するはずです(複数行の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>

あなたはあなたのコードからもそれを行うことができるはずです

6

ネストされたjsonを読んでいるjsonが1行にあることを確認してください。すでにこれを行っている場合は、ネストされた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
Sandeep Purohit

このスレッドは少し古いので、@ user6022341が提案したことについて詳しく説明したいと思います。私はそれを私のプロジェクトの1つとして使用することになりました:

複数行のjsonファイルを処理するには、ファイルが1つの大きなjsonオブジェクトである場合、wholeTextFiles(String path)変換がsparkの唯一のソリューションです。この変換により、ファイルの内容全体が文字列として読み込まれます。したがって、hdfs:// a-hdfs-pathディレクトリに、part-00000とpart-00001の2つのファイルがある場合。 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-1961

https://issues.Apache.org/jira/browse/SPARK-2098

これが同様の情報を探している他の人々に役立つことを願っています。

0
skvyas

Java in Sparkを使用して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();
0
RPaul

試してください:

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