Я намагався використовувати файл JSON як невелику БД. Після створення таблиці шаблонів на 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|
| }|
+--------------------+
UPD2
Це дивно, але коли я переписую свій JSON, щоб зробити його однолінійним, все працює нормально.
{"id": 1, "name": "Morty", "age": 21}
Отже, проблема в newline
.
UPD3
Я знайшов у документах наступне речення:
Зверніть увагу, що файл, який пропонується як файл jsonне є типовим файлом JSON. Кожен рядок повинен містити окремий, автономний дійсний об'єкт JSON. Як наслідок, звичайний багаторядковий файл JSON найчастіше виходить з ладу.
Зберігати JSON у такому форматі не зручно. Чи існує якийсь обхідний спосіб, щоб позбутися багаторядкової структури JSON або перетворити її в oneliner?
Відповіді:
21 для відповіді № 1Іскра> = 2.2
Введено Spark 2.2 wholeFile
multiLine
варіант, який можна використовувати для завантаження файлів JSON (а не JSONL):
spark.read
.option("multiLine", true).option("mode", "PERMISSIVE")
.json("/path/to/user.json")
Побачити:
- ІСКРА-18352 - Розбір звичайних багаторядкових файлів JSON (не тільки рядків JSON).
- ІСКРА-20980 - Перейменуйте опцію
wholeFile
доmultiLine
для JSON та CSV.
Іскра <2.2
Ну, використання форматованих даних JSONL може бутинезручно, але це я заперечую, що справа не в API, а в самому форматі. JSON просто не призначений для паралельної обробки в розподілених системах.
Він не надає схеми і не робить деякихдуже конкретні припущення щодо форматування та форми майже неможливо правильно визначити документи вищого рівня. Можливо, це найгірший з можливих форматів, який можна використовувати в таких системах, як Apache Spark. Також досить складно і, як правило, непрактично писати дійсний JSON у розподілених системах.
При цьому, якщо окремі файли є дійсними документами JSON (або один документ, або масив документів), ви завжди можете спробувати wholeTextFiles
:
spark.read.json(sc.wholeTextFiles("/path/to/user.json").values())
3 для відповіді № 2
Просто для того, щоб додати відповідь до нуля 323, опцію в 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-20980.