Перейти к содержимому
Последнее обновление

JSON | Формат файла

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

Способы импорта​

Следующие способы импорта поддерживают данные в формате JSON:

Способ импортаСценарий примененияПередача параметров
Stream LoadИмпорт небольшими пакетами почти в реальном времени с отправкой данных с локального компьютера или из клиентаHTTP Header, например -H "jsonpaths: $.data"
Broker LoadМассовый импорт больших файлов из объектного хранилища, HDFS и аналогичных источниковPROPERTIES, например PROPERTIES("jsonpaths"="$.data")
Routine LoadНепрерывное получение JSON из очередей сообщений, таких как KafkaPROPERTIES, например PROPERTIES("jsonpaths"="$.data")
INSERT INTO FROM S3 TVFЧтение файлов JSON в S3 напрямую с помощью SQLПараметры TVF, например S3("jsonpaths"="$.data")
INSERT INTO FROM HDFS TVFЧтение файлов JSON в HDFS напрямую с помощью SQLПараметры TVF

Поддерживаемые форматы JSON​

Doris поддерживает следующие три варианта организации файлов JSON, каждый из которых подходит для определённых бизнес-сценариев.

Формат 1: Несколько строк в виде массива​

Подходит для массового импорта нескольких строк за один раз.

Требования:

  • Корневой узел должен быть массивом.
  • Каждый элемент массива должен быть объектом, представляющим одну строку данных.
  • Необходимо задать strip_outer_array=true.

Пример данных:

[
{"id": 123, "city": "beijing"},
{"id": 456, "city": "shanghai"}
]

// Nested structures are supported
[
{"id": 123, "city": {"name": "beijing", "region": "haidian"}},
{"id": 456, "city": {"name": "beijing", "region": "chaoyang"}}
]

Формат 2: Одна строка в виде объекта​

Подходит для импорта одной строки данных.

Требования:

  • Корневой узел должен быть объектом.
  • Весь объект представляет одну строку данных.
  • В каждой строке файла должна быть только одна запись JSON.

Пример данных:

{"id": 123, "city": "beijing"}

// Nested structures are supported
{"id": 123, "city": {"name": "beijing", "region": "haidian"}}
Примечание

Этот формат обычно используется с Routine Load, например для отдельного сообщения в Kafka.

Формат 3: Несколько строк объектов, разделённых фиксированным разделителем​

Подходит для массового импорта нескольких строк, каждая из которых является отдельным объектом JSON (аналогично NDJSON).

Требования:

  • Каждая строка должна содержать полный объект JSON.
  • Явно задавать read_json_by_line=true не требуется: этот режим включён по умолчанию.
  • Разделитель строк можно указать с помощью параметра line_delimiter; по умолчанию используется \n.

Пример данных:

{"id": 123, "city": "beijing"}
{"id": 456, "city": "shanghai"}

Настройка параметров​

Матрица поддержки параметров для каждого способа импорта​

В следующей таблице показана поддержка параметров JSON для разных способов импорта:

ПараметрЗначение по умолчаниюStream LoadBroker LoadRoutine LoadTVF
jsonpathsНе заданоПоддерживаетсяПоддерживаетсяПоддерживаетсяПоддерживается
json_rootНе заданоПоддерживаетсяПоддерживаетсяПоддерживаетсяПоддерживается
strip_outer_arrayfalseПоддерживаетсяПоддерживаетсяПоддерживаетсяПоддерживается
read_json_by_linetrueПоддерживаетсяНе настраиваетсяНе настраиваетсяПоддерживается
fuzzy_parsefalseПоддерживаетсяПоддерживаетсяНе поддерживаетсяПоддерживается
num_as_stringfalseПоддерживаетсяПоддерживаетсяПоддерживаетсяПоддерживается
Формат сжатияplainПоддерживаетсяПоддерживаетсяНе поддерживаетсяПоддерживается
Передача параметров и поведение по умолчанию
  1. Stream Load: параметры передаются напрямую через HTTP Header, например -H "jsonpaths: $.data".
  2. Broker Load: параметры передаются через PROPERTIES, например PROPERTIES("jsonpaths"="$.data").
  3. Routine Load: параметры передаются через PROPERTIES, например PROPERTIES("jsonpaths"="$.data").
  4. TVF: параметры передаются в выражении TVF, например S3("jsonpaths"="$.data").
  5. Чтобы напрямую импортировать объект JSON из корневого узла файла JSON, задайте для jsonpaths значение $., например PROPERTIES("jsonpaths"="$.").
  6. Значение read_json_by_line по умолчанию равно true. Это означает, что, если при импорте не указан ни strip_outer_array, ни read_json_by_line, значение read_json_by_line равно true.
  7. read_json_by_line не настраивается в Broker Load и Routine Load. Для него принудительно устанавливается true, чтобы обеспечить потоковое чтение и снизить нагрузку на память BE.

Подробное описание параметров​

jsonpaths​

  • Назначение: Задаёт способ извлечения полей из данных JSON.

  • Тип: Массив строк.

  • Значение по умолчанию: Не задано. По умолчанию столбцы сопоставляются по имени.

  • Примеры:

    -- Basic usage
    ["$.id", "$.city"]

    -- Nested structure
    ["$.id", "$.info.city", "$.data[0].name"]

json_root​

  • Назначение: Задаёт начальную точку разбора данных JSON.

  • Тип: Строка.

  • Значение по умолчанию: Не задано. По умолчанию разбор начинается с корневого узла.

  • Примеры:

    -- Original data
    {
    "data": {
    "id": 123,
    "city": "beijing"
    }
    }

    -- Set json_root
    json_root = $.data

strip_outer_array​

  • Назначение: Определяет, нужно ли удалять внешнюю структуру массива.

  • Тип: Логическое значение.

  • Значение по умолчанию: false.

  • Примеры:

    -- Original data
    [
    {"id": 1, "city": "beijing"},
    {"id": 2, "city": "shanghai"}
    ]

    -- Set strip_outer_array=true

read_json_by_line​

  • Назначение: Определяет, нужно ли читать данные JSON построчно.

  • Тип: Логическое значение.

  • Значение по умолчанию: true, если strip_outer_array не задан; при указании strip_outer_array=true значением по умолчанию становится false. (Broker Load и Routine Load всегда принудительно устанавливают read_json_by_line=true.)

  • Примеры:

    -- Original data (one complete JSON object per line)
    {"id": 1, "city": "beijing"}
    {"id": 2, "city": "shanghai"}

    -- Set read_json_by_line=true

fuzzy_parse​

  • Назначение: Ускоряет импорт данных JSON.
  • Тип: Логическое значение.
  • Значение по умолчанию: false.
  • Ограничения:
    • Порядок полей в каждой строке массива должен быть строго одинаковым.
    • Обычно используется вместе с strip_outer_array.
  • Производительность: Повышает скорость импорта в 3–5 раз.

num_as_string​

  • Назначение: Определяет, нужно ли разбирать числовые значения в JSON как строки.

  • Тип: Логическое значение.

  • Значение по умолчанию: false.

  • Сценарии использования:

    • Обработка чисел, выходящих за пределы поддерживаемого числового диапазона.
    • Предотвращение потери точности чисел.
  • Пример:

    -- Original data
    {
    "id": "12345678901234567890",
    "price": "99999999.999999"
    }
    -- With num_as_string=true, the price field is parsed as a string

Связь между JSON Path и Columns​

При импорте данных jsonpaths и columns выполняют разные задачи:

ПараметрЗадачаРезультат
jsonpathsОпределяет правила извлечения данныхИзвлекает поля из данных JSON по указанным путям и упорядочивает их в соответствии с порядком, заданным в jsonpaths
columnsОпределяет правила сопоставления данныхСопоставляет извлечённые поля со столбцами целевой таблицы, при необходимости изменяя порядок столбцов и преобразуя значения

Они обрабатываются последовательно:

  1. Сначала jsonpaths извлекает поля из исходных данных и формирует упорядоченный набор данных.
  2. Затем columns сопоставляет эти элементы данных со столбцами таблицы.

Если columns не указан, извлечённые поля сопоставляются напрямую в порядке столбцов таблицы.

Пример 1: Использование только JSON Path​

Схема таблицы и данные:

-- Table schema
CREATE TABLE example_table (
k2 int,
k1 int
);

-- JSON data
{"k1": 1, "k2": 2}

Команда импорта:

curl -v ... -H "format: json" \
-H "jsonpaths: [\"$.k2\", \"$.k1\"]" \
-T example.json \
http://<fe_host>:<fe_http_port>/api/db_name/table_name/_stream_load

Результат импорта:

+------+------+
| k1 | k2 |
+------+------+
| 2 | 1 |
+------+------+

Пример 2: Совместное использование JSON Path и Columns​

Используйте ту же схему таблицы и те же данные, что и выше, и добавьте параметр columns.

Команда импорта:

curl -v ... -H "format: json" \
-H "jsonpaths: [\"$.k2\", \"$.k1\"]" \
-H "columns: k2, k1" \
-T example.json \
http://<fe_host>:<fe_http_port>/api/db_name/table_name/_stream_load

Результат импорта:

+------+------+
| k1 | k2 |
+------+------+
| 1 | 2 |
+------+------+

Пример 3: Повторное использование поля​

Схема таблицы и данные:

-- Table schema
CREATE TABLE example_table (
k2 int,
k1 int,
k1_copy int
);

-- JSON data
{"k1": 1, "k2": 2}

Команда импорта:

curl -v ... -H "format: json" \
-H "jsonpaths: [\"$.k2\", \"$.k1\", \"$.k1\"]" \
-H "columns: k2, k1, k1_copy" \
-T example.json \
http://<fe_host>:<fe_http_port>/api/db_name/table_name/_stream_load

Результат импорта:

+------+------+---------+
| k2 | k1 | k1_copy |
+------+------+---------+
| 2 | 1 | 1 |
+------+------+---------+

Пример 4: Сопоставление вложенных полей​

Схема таблицы и данные:

-- Table schema
CREATE TABLE example_table (
k2 int,
k1 int,
k1_nested1 int,
k1_nested2 int
);

-- JSON data
{
"k1": 1,
"k2": 2,
"k3": {
"k1": 31,
"k1_nested": {
"k1": 32
}
}
}

Команда импорта:

curl -v ... -H "format: json" \
-H "jsonpaths: [\"$.k2\", \"$.k1\", \"$.k3.k1\", \"$.k3.k1_nested.k1\"]" \
-H "columns: k2, k1, k1_nested1, k1_nested2" \
-T example.json \
http://<fe_host>:<fe_http_port>/api/db_name/table_name/_stream_load

Результат импорта:

+------+------+------------+------------+
| k2 | k1 | k1_nested1 | k1_nested2 |
+------+------+------------+------------+
| 2 | 1 | 31 | 32 |
+------+------+------------+------------+

Примеры использования​

В этом разделе показано, как использовать формат JSON с каждым способом импорта. Приведённые фрагменты можно копировать и адаптировать под свои задачи.

Stream Load​

# Use JSON Path
curl --location-trusted -u <user>:<passwd> \
-H "format: json" \
-H "jsonpaths: [\"$.id\", \"$.city\"]" \
-T example.json \
http://<fe_host>:<fe_http_port>/api/example_db/example_table/_stream_load

# Specify JSON root
curl --location-trusted -u <user>:<passwd> \
-H "format: json" \
-H "json_root: $.events" \
-T example.json \
http://<fe_host>:<fe_http_port>/api/example_db/example_table/_stream_load

# Read JSON line by line
curl --location-trusted -u <user>:<passwd> \
-H "format: json" \
-H "read_json_by_line: true" \
-T example.json \
http://<fe_host>:<fe_http_port>/api/example_db/example_table/_stream_load

Broker Load​

-- Use JSON Path
LOAD LABEL example_db.example_label
(
DATA INFILE("s3://bucket/path/example.json")
INTO TABLE example_table
FORMAT AS "json"
PROPERTIES
(
"jsonpaths" = "[\"$.id\", \"$.city\"]"
)
)
WITH S3
(
...
);

-- Specify JSON root
LOAD LABEL example_db.example_label
(
DATA INFILE("s3://bucket/path/example.json")
INTO TABLE example_table
FORMAT AS "json"
PROPERTIES
(
"json_root" = "$.events"
)
)
WITH S3
(
...
);

Routine Load​

-- Use JSON Path
CREATE ROUTINE LOAD example_db.example_job ON example_table
PROPERTIES
(
"format" = "json",
"jsonpaths" = "[\"$.id\", \"$.city\"]"
)
FROM KAFKA
(
...
);

TVF​

-- Use JSON Path
INSERT INTO example_table
SELECT *
FROM S3
(
"uri" = "s3://bucket/example.json",
"format" = "json",
"jsonpaths" = "[\"$.id\", \"$.city\"]",
...
);

-- Specify JSON root
INSERT INTO example_table
SELECT *
FROM S3
(
"uri" = "s3://bucket/example.json",
"format" = "json",
"json_root" = "$.events",
...
);

Часто задаваемые вопросы​

Вопрос 1: Почему при импорте файла JSON в виде массива все данные обрабатываются как одна строка?​

Необходимо явно задать strip_outer_array=true. В противном случае Doris разбирает весь внешний массив как один объект JSON и не может записывать данные построчно.

Вопрос 2: Как импортировать файл, в котором каждая строка содержит один объект JSON (NDJSON)?​

Импортируйте его напрямую, используя формат 3. read_json_by_line включён по умолчанию, поэтому дополнительная настройка не требуется. Если разделитель строк отличается от \n, укажите его с помощью line_delimiter.

Вопрос 3: Как напрямую импортировать объект JSON из корневого узла файла JSON?​

Задайте для jsonpaths значение $., например PROPERTIES("jsonpaths"="$.").

Вопрос 4: Как избежать потери точности для очень больших чисел или десятичных чисел высокой точности?​

Задайте num_as_string=true. Числовые значения в JSON разбираются как строки, а затем записываются в столбцы соответствующих типов, что позволяет избежать числового переполнения и потери точности.

Вопрос 5: Почему Broker Load / Routine Load не позволяют настраивать read_json_by_line?​

Чтобы снизить нагрузку на память BE, Broker Load и Routine Load всегда читают данные построчно в потоковом режиме. Поэтому read_json_by_line нельзя настроить явно.

Вопрос 6: Как ускорить импорт большого количества массивов JSON с одинаковой структурой?​

Включите fuzzy_parse=true вместе с strip_outer_array=true, чтобы повысить скорость импорта в 3–5 раз. Порядок полей в каждой строке массива должен быть строго одинаковым.

Вопрос 7: Как связаны jsonpaths и columns и какой параметр применяется первым?​

Сначала jsonpaths извлекает поля из JSON и располагает их в заданном порядке, а затем columns сопоставляет эти поля со столбцами целевой таблицы. Подробнее см. в разделе Связь между JSON Path и Columns.

На этой странице