Работаем с файлами JSON в PySpark: читаем и записываем

Сегодня расскажем, как работать с файлами формата JSON в PySpark. В этой статье вы узнаете: как прочитать файл JSON, каким должен быть формат, чтобы PySpark прочитал его корректно, и как записать файл JSON.

Что такое JSON

JSON (JavaScript Object Notation) — это формат для хранения данных. Несмотря на свое название, он применяется не только в проектах с JavaScript. Есть даже СУБД, например, MongoDB, основной формат, которых это JSON.

Основное преимущество этого формата — читаемость. Причем люди, работающие с Python, не найдут его сложным (в отличие от XML, например).

Составные объекты помещаются в фигурные скобки, массивы в квадратные, атрибуты и строки в двойные кавычки. Также имеется специальный символ — null, обозначающий нулевое значение объекта. Пример JSON, представляющий человека:

{
  "firstName": "John",
  "isAlive": true,
  "age": 27,
  "address": {
    "streetAddress": "21 2nd Street",
    "city": "New York",
  },
  "phoneNumbers": [
    {
      "type": "home",
      "number": "212 555-1234"
    },
    {
      "type": "office",
      "number": "646 555-4567"
    }
  ],
  "children": ["Alex", "Anna"],
  "spouse": null
}

Очень важным моментом является отсутствие запятой у самого последнего атрибута. В Python в некоторых случаях разрешено оставлять, здесь же — нет.

Читаем JSON файлы в DataFrame

Во-первых, следует знать, что, в отличие от чтения CSV, по умолчанию чтение JSON применяет определение типов (inferschema); это значит, что если файл большой, то читаться он будет не быстро.

Графовые алгоритмы в Apache Spark

Код курса
GRAS
Ближайшая дата курса
16 мая, 2024
Продолжительность
16 ак.часов
Стоимость обучения
48 000 руб.

Во-вторых, по умолчанию однострочное чтение. Это значит, что каждый объект, которая в итоге должна быть интерпретирована как строка DataFrame, должен находиться на одной строке. Поэтому пример выше он не прочитает, если не дать дополнительные аргументы.

Например, есть JSON-файл:

{ "name": "John", "age": 27 },
{ "name": "Alex", "age": 32 },
{ "name": "Anna", "age": null }

Тогда его чтение осуществляется очень просто:

df = spark.read.json("data.json")
df.show()
"""
+----+----+
| age|name|
+----+----+
|  27|John|
|  32|Alex|
|null|Anna|
+----+----+
"""

Чтение многострочных JSON-файлов

Если же объект задан в многострочном виде, например, так (или просто объекты в виде списка):

[{
    "name": "John",
    "age": 27
},
{
    "name": "Alex",
    "age": 32
},
{
    "name": "Anna",
    "age": null
}]

Тогда прочитать его можно следующим образом:

spark.read.json("data.json", multiLine=True)

Либо так:

df = spark.read.option("multiline", "true").json("data.json")

Обратите внимание на то, что объекты заключены в квадратные скобки. Иначе, PySpark прочитал бы JSON неправильно. С другой стороны, если у вас однострочники и они не определены как массив, т.е. не заключены в квадратные скобки, то при значение multiLine=True, файл также будет прочитан неправильно. Поэтому будьте осторожны.

Чтение нескольких JSON-файлов одновременно

Чтобы прочитать несколько файлов, передайте их пути в виде списка:

df = spark.read.json(["data.json", "data2.json"], multiLine=True)
df.show()
"""
+----+----+
| age|name|
+----+----+
|  27|John|
|  32|Alex|
|null|Anna|
|  77|Mila|
|  33|Gowl|
|  15|Bona|
+----+----+
"""

Можно использовать групповые символы, например:

df = spark.read.json("/full/path/*.json")

Как уже было сказано, неправильное чтение может произойти, если в одном файле однострочнике, а в другом нет. Тогда вы можете прочитать их по отдельности, а затем соединить друг с другом (об этом мы рассказывали в статье):

df1 = spark.read.json("data.json", multiLine=True)
df2 = spark.read.json("data2.json")
df = df1.union(df2)

Чтение с заданной схемой

Чтобы ускорить процесс чтения, можно не использовать inferSchema. Для этого нужно определить структуру таблицы (схема). Например, в нашем случае имеется два поля, тогда схема будет иметь вид:

from pyspark.sql.types import StructField, IntegerType, StringType
schema = StructType([
    StructField("name", StringType()),
    StructField("age", IntegerType())
])
df = spark.read.json("data.json", schema, multiLine=True).show()

Однако это работает только с заранее известной схемой.

Запись в JSON в PySpark

Для записи используйте метод write.json, который создает директорию, в которую записывает в виде партиций сам файл. В качестве опционального параметра (mode) можно дать:

  • append добавить в конец существующего файла;
  • overwrite перезаписать файл, тогда старые данные будут утеряны;
  • ignore не записывать в файл, если файл уже существует;
  • error выдать ошибку, если файл уже существует (используется по умолчанию).
# Будет создана директория, в которой будет лежать файл
df.write.json("new", mode="append")

 

В следующей статье познакомимся с функциями для работы с JSON-файлами. О том, как работать с JSON и другими форматами в PySpark вы узнаете на наших образовательных курсах в лицензированном учебном центре обучения и повышения квалификации руководителей и ИТ-специалистов (менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data) в Москве:

Записаться на курс

Смотреть раcписание

Источники
  1. JSON в Википедии
  2. DataFrameReader.json
  3. DataFrameWriter.json

Добавить комментарий

Поиск по сайту