JavaRush /Курсы /SQL SELF /Извлечение данных из JSON-объектов

Извлечение данных из JSON-объектов

SQL SELF
33 уровень , 2 лекция
Открыта

JSONB — это мощный инструмент, который позволяет хранить сложные структуры данных, такие как вложенные объекты или массивы. Однако просто хранить данные в JSONB недостаточно — мы должны уметь извлекать эти данные. Например, представьте, что у вас есть колонка data в таблице users, где хранятся все пользовательские настройки в формате JSONB. Хотите узнать, какая тема оформления выбрана у пользователя? Придётся извлечь её из JSONB-объекта.

Если JSONB — это сундук с сокровищами, то операторы ->, ->>, #>> и функции, такие как jsonb_extract_path(), — это ваши ключи. Давайте разбираться, как ими пользоваться.

Основные операторы для работы с JSONB

В PostgreSQL предусмотрено несколько ключевых операторов для работы с JSONB. Они позволяют извлекать значения из ключей, вложенных объектов и массивов. Вот основные из них:

Оператор ->

Оператор -> извлекает объект или массив по заданному ключу. Если вы хотите получить значение в том же формате, что и в JSON, этот оператор — ваш выбор.

Пример:

-- Пример данных
SELECT '{"name": "Alice", "age": 25}'::jsonb -> 'name';
-- Результат: "Alice"

Оператор ->>

Оператор ->> похож на ->, но он возвращает извлечённое значение в виде текста. Это полезно, когда вы хотите получить упрощённое текстовое представление данных.

Пример:

-- Пример данных
SELECT '{"name": "Alice", "age": 25}'::jsonb ->> 'age';
-- Результат: "25" (строка)

Оператор #>>

Оператор #>> извлекает данные из вложенных объектов по указанному пути. Путь передаётся в виде массива ключей.

Пример:

-- Пример данных
SELECT '{"user": {"name": "Bob", "details": {"age": 30}}}'::jsonb #>> '{user, details, age}';
-- Результат: "30" (строка)

Разница между -> и ->>:

Если вам важно сохранить тип данных (например, массив или объект), используйте ->. Если вам нужен текст, берите ->>.

Использование функций для работы с JSONB

Функция jsonb_extract_path() извлекает значение из JSONB-объекта по указанному пути. Это функциональный аналог оператора #>>, но немного более выразительный.

Пример:

SELECT jsonb_extract_path('{"user": {"name": "Alice", "settings": {"theme": "dark"}}}'::jsonb, 'user', 'settings', 'theme');
-- Результат: "dark"

Если вы хотите сразу получить текстовое значение, используйте jsonb_extract_path_text(). Она работает так же, как jsonb_extract_path(), но возвращает строку.

Пример:

SELECT jsonb_extract_path_text('{"user": {"name": "Alice", "settings": {"theme": "dark"}}}'::jsonb, 'user', 'settings', 'theme');
-- Результат: dark

Практические примеры

Извлечение значения по ключу. Допустим, у нас есть таблица products, где в колонке details хранятся данные в формате JSONB:

CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    name TEXT,
    details JSONB
);

INSERT INTO products (name, details) VALUES
    ('Laptop', '{"brand": "Dell", "price": 1200, "specs": {"ram": "16GB", "cpu": "Intel i7"}}'),
    ('Phone', '{"brand": "Apple", "price": 1000, "specs": {"ram": "4GB", "cpu": "A13"}}');

Результат:

id name details
1 Laptop {"brand": "Dell", "price": 1200, "specs": {"ram": "16GB", "cpu": "Intel i7"}}
2 Phone {"brand": "Apple", "price": 1000, "specs": {"ram": "4GB", "cpu": "A13"}}

Извлечём бренды всех продуктов.

SELECT name, details->'brand' AS brand FROM products;

Результат:

name brand
Laptop "Dell"
Phone "Apple"

Извлечение текстового значения. Если нам нужен бренд без кавычек, используем оператор ->>:

SELECT name, details->>'brand' AS brand FROM products;

Результат:

name brand
Laptop Dell
Phone Apple

Извлечение вложенных данных. Извлечём объём оперативной памяти (ram) для каждого продукта:

SELECT name, details#>>'{specs, ram}' AS ram FROM products;

Результат:

name ram
Laptop 16GB
Phone 4GB

Извлечение данных по пути. То же самое можно сделать с функцией jsonb_extract_path_text():

SELECT name, jsonb_extract_path_text(details, 'specs', 'ram') AS ram FROM products;

Результат:

name ram
Laptop 16GB
Phone 4GB

Типичные ошибки и как их избежать

Ошибки часто встречаются, когда вы:

  • Пытаетесь извлечь данные по неверному пути. Например, если ключа не существует, результат будет null.
  • Используете неправильный оператор для задачи. -> подходит для извлечения объектов и массивов, но для текста нужно применять ->>.

Пример ошибки:

-- Ошибка: ключа 'nonexistent' нет
SELECT details->>'nonexistent' FROM products;
-- Результат: null

Совет: всегда проверяйте структуру данных перед написанием запросов, чтобы избежать ошибок.

Применение в реальных задачах

Извлечение данных из JSONB используется во многих реальных приложениях:

  • В e-commerce для работы с характеристиками товаров.
  • В веб-приложениях для хранения пользовательских настроек.
  • В аналитике для обработки структурированных данных, таких как события и логи.

Вот ещё один пример. Допустим, у нас есть таблица orders, где хранятся данные о заказах:

CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    customer_name TEXT,
    items JSONB
);

INSERT INTO orders (customer_name, items) VALUES
    ('John', '[{"product": "Laptop", "quantity": 1}, {"product": "Mouse", "quantity": 2}]'),
    ('Alice', '[{"product": "Phone", "quantity": 1}]');

Извлечём названия всех продуктов из заказов:

SELECT customer_name, jsonb_array_elements(items)->>'product' AS product FROM orders;

Результат:

customer_name product
John Laptop
John Mouse
Alice Phone

Далее мы углубимся в работу с JSONB, исследуя вложенные данные и преобразование их в более удобный для анализа вид. Будьте готовы к ещё более интересным открытиям!

2
Задача
SQL SELF, 33 уровень, 2 лекция
Недоступна
Извлечение данных из JSON-объекта с помощью оператора `->`
Извлечение данных из JSON-объекта с помощью оператора `->`
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Евгений Уровень 49 Expert
10 сентября 2025
Насчёт оператора #>>. Можно также использовать #>, он возвращает JSON-ноду вместо текста.