web-dev-qa-db-ja.com

Apacheで複数行のJSONを読み取るSpark

JSONファイルを小さなDBとして使用しようとしていました。 DataFrameでテンプレートテーブルを作成した後、SQLでクエリを実行すると例外が発生しました。ここに私のコードがあります:

_val df = sqlCtx.read.json("/path/to/user.json")
df.registerTempTable("user_tt")

val info = sqlCtx.sql("SELECT name FROM user_tt")
info.show()
_

df.printSchema()結果:

_root
 |-- _corrupt_record: string (nullable = true)
_

私のJSONファイル:

_{
  "id": 1,
  "name": "Morty",
  "age": 21
}
_

例外:

_Exception in thread "main" org.Apache.spark.sql.AnalysisException: cannot resolve 'name' given input columns: [_corrupt_record];
_

どうすれば修正できますか?

[〜#〜] upd [〜#〜]

__corrupt_record_は

_+--------------------+
|     _corrupt_record|
+--------------------+
|                   {|
|            "id": 1,|
|    "name": "Morty",|
|           "age": 21|
|                   }|
+--------------------+
_

PD2

奇妙ですが、JSONを書き直してonelinerにすると、すべて正常に動作します。

_{"id": 1, "name": "Morty", "age": 21}
_

したがって、問題はnewlineにあります。

PD

私はドキュメントで次の文を見つけました:

Jsonファイルとして提供されるファイルは、一般的なJSONファイルではないことに注意してください。各行には、独立した独立した有効なJSONオブジェクトが含まれている必要があります。結果として、通常の複数行JSONファイルはほとんどの場合失敗します。

JSONをこのような形式に保つのは便利ではありません。 JSONの複数行構造を取り除く、またはonelinerで変換する回避策はありますか?

19
Finkelson

Spark> = 2.2

Spark 2.2が導入されました wholeFile JSON(JSONLではない)ファイルのロードに使用できるmultiLineオプション:

spark.read
  .option("multiLine", true).option("mode", "PERMISSIVE")
  .json("/path/to/user.json")

見る:

  • SPARK-18352 -通常の複数行JSONファイル(JSON行だけでなく)を解析します
  • SPARK-2098 -JSONおよびCSVのオプションの名前をwholeFileからmultiLineに変更します。

スパーク<2.2

まあ、JSONL形式のデータを使用するのは不便かもしれませんが、それはAPIの問題ではなく、形式そのものです。 JSONは、分散システムで並列処理されるように設計されていないだけです。

それはスキーマを提供せず、その書式設定と形状についていくつかの非常に具体的な仮定を行うことなく、トップレベルのドキュメントを正しく識別することはほとんど不可能です。おそらくこれは、Apache Sparkのようなシステムで使用するために想像できる最悪の形式です。また、分散システムで有効なJSONを記述することは非常に難しく、通常は実用的ではありません。

つまり、個々のファイルが有効なJSONドキュメント(単一のドキュメントまたはドキュメントの配列)である場合は、常にwholeTextFilesを試すことができます。

spark.read.json(sc.wholeTextFiles("/path/to/user.json").values())
41
zero323

Zero323の答えに追加するために、Spark 2.2+の複数行JSONを読み取るオプションがmultiLineに名前が変更されました(Spark =ドキュメント ここ )。

したがって、正しい構文は次のとおりです。

spark.read
  .option("multiLine", true).option("mode", "PERMISSIVE")
  .json("/path/to/user.json")

これは https://issues.Apache.org/jira/browse/SPARK-2098 で発生しました。

7
Dan Coates