Читайте многострочный JSON в Apache Spark

Я пытался использовать 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
}

Exeption:

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, чтобы сделать его oneliner, все работает нормально.

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

Итак, проблема в newline.

UPD3

Я нашел в документах следующее предложение:

Обратите внимание, что файл, который предлагается в виде json файла, не является типичным файлом JSON. Каждая строка должна содержать отдельный автономный действительный объект JSON. Как следствие, обычный многострочный файл JSON чаще всего терпит неудачу.

Невозможно сохранить JSON в таком формате. Есть ли какое-либо обходное решение, чтобы избавиться от многослойной структуры JSON или преобразовать ее в oneliner?

Ответ 1

Искры> = 2,2

Spark 2.2 представил wholeFile multiLine которая может использоваться для загрузки файлов JSON (не JSONL):

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

Видеть:

  • SPARK-18352 - Разбирайте обычные многострочные файлы JSON (а не только линии JSON).
  • SPARK-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())

Ответ 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.