ГлавнаяАкадемияNode-RED: установка, flows, msg/JSON, отладка → Введение в JSONata: что это и зачем нужно

Введение в JSONata: что это и зачем нужно

Урок 4 · Node-RED: установка, flows, msg/JSON, отладка · 30 мин · theory

Что такое JSONata и ее роль в Node-RED

В предыдущих уроках мы научились управлять потоком сообщений с помощью нод `Change` и `Switch`. Однако по мере усложнения задач автоматизации возрастает и сложность данных, которыми мы оперируем. Показания с датчиков, ответы от API, команды от интерфейсов пользователя — все это приходит в виде JSON-объектов разной структуры. Перед инженером встает задача: как эффективно и надежно извлекать, преобразовывать и комбинировать эти данные?

Одним из решений является использование ноды `Function` и написание кода на JavaScript. Но этот подход требует знаний программирования и может усложнить поддержку потоков. Для решения этой проблемы в ядро Node-RED встроен мощный инструмент — JSONata.

> 💡 Подсказка: Для экспериментов с JSONata в реальном времени используйте официальный онлайн-редактор JSONata Exerciser. Это отличный способ протестировать сложные выражения перед их внедрением в поток Node-RED. Вы можете вставить свой JSON-объект и в интерактивном режиме подбирать правильное выражение для извлечения или трансформации данных.

JSONata — это легковесный язык запросов и преобразований, специально созданный для работы с данными в формате JSON. Его можно сравнить с языком SQL, который используется для работы с реляционными базами данных.

| Характеристика | SQL (для баз данных) | JSONata (для JSON) |

| :--- | :--- | :--- |

| Объект работы | Структурированные таблицы с рядами и колонками | Структурированные JSON-документы с объектами и массивами |

| Основная задача | `SELECT`, `UPDATE`, `INSERT`, `DELETE` данные | Выборка, трансформация, фильтрация, агрегация данных |

| Пример | `SELECT temperature FROM sensors WHERE room = 'office'` | `payload[room='office'].temperature` |

Роль JSONata в Node-RED — предоставить инженеру-автоматизатору декларативный, то есть описательный, способ манипуляции данными без необходимости прибегать к императивному программированию на JavaScript. Вместо того чтобы писать пошаговую инструкцию "возьми это поле, умножь его на 10, добавь к нему другое поле и положи результат сюда", вы просто описываете конечный результат, который хотите получить.

Ключевое отличие JSONata от простого доступа к свойствам объекта `msg` (например, `msg.payload.temperature`) заключается в том, что JSONata — это не просто указатель пути, а полноценный язык выражений. Он позволяет:

Интеграция JSONata непосредственно в стандартные ноды (`Change`, `Switch`, `Inject`, `Template`) превращает их из простых инструментов в гибкие процессоры данных, что кардинально повышает мощь и выразительность ваших потоков, сохраняя при этом их визуальную простоту и читаемость.

---

Базовый синтаксис: выборка данных из объекта msg

Основа работы с JSONata — это умение точно указывать путь к нужным данным внутри входящего объекта `msg`. По умолчанию любое JSONata-выражение в Node-RED выполняется в контексте всего объекта `msg`, что дает нам доступ ко всем его свойствам: `payload`, `topic`, `_msgid` и другим.

📋 Ключевые понятия:

Рассмотрим основные способы выборки данных на примере типового сообщения от мультисенсора, подключенного к контроллеру.

Пример входящего сообщения `msg`:
{

"_msgid": "a1b2c3d4.5e4f56",

"topic": "telemetry/office/room-101",

"payload": {

"device-id": "MODBUS-TH-01",

"timestamp": 1678886400000,

"location": "Room 101",

"values": [

{ "type": "temperature", "value": 23.5, "unit": "°C" },

{ "type": "humidity", "value": 45.2, "unit": "%" }

],

"status": {

"battery_level": 98,

"signal_strength": -75

}

}

}

Доступ к свойствам через точечную нотацию (Dot Notation)

Это самый распространенный и интуитивно понятный способ. Используйте точку `.` для навигации по иерархии объекта.

`payload` -> вернет объект `{"device-id": "...", ...}` `payload.timestamp` -> вернет число `1678886400000` `topic` -> вернет строку `"telemetry/office/room-101"`

Работа с вложенными объектами

Правило точечной нотации применяется и для вложенных структур. Просто продолжайте цепочку.

`payload.status.battery_level` -> вернет число `98`

Обращение к элементам массива по индексу

Для доступа к элементам массива используются квадратные скобки `[]` с указанием индекса элемента (нумерация начинается с 0).

`payload.values[0]` -> вернет `{ "type": "temperature", "value": 23.5, "unit": "°C" }` `payload.values[0].value` -> вернет число `23.5` `payload.values[1].unit` -> вернет строку `"%"`

Использование скобочной нотации для свойств со спецсимволами

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

`payload.['device-id']` -> вернет строку `"MODBUS-TH-01"`

Этот синтаксис незаменим при работе с данными из внешних систем, которые не придерживаются конвенции `camelCase` или `snake_case` в именовании ключей.

Освоение этих простых правил выборки — это первый и самый важный шаг в работе с JSONata. Он позволяет вам "дотянуться" до любого фрагмента данных в самом сложном JSON-объекте.

---

Применение в нодах: Change и Switch

Теория без практики мертва. Давайте посмотрим, как JSONata раскрывает свой потенциал в двух самых часто используемых нодах для манипуляции данными.

> 🔗 Связанный материал: Мы уже рассматривали ноды `Change` и `Switch` в уроках COURSE-06-M03-L02 и COURSE-06-M03-L03. Теперь вы видите, как JSONata расширяет их функциональность, позволяя перейти от статических правил к динамическим трансформациям и сложной логике.

Пример 1: Форматирование данных в ноде `Change`

Представим, что с релейного модуля, подключенного по Modbus, мы получаем показания тока в миллиамперах (мА) в виде простого числа в `msg.payload`. Наша задача — преобразовать это сообщение в стандартизированный формат, понятный для системы мониторинга: с явным значением в амперах (А) и метаданными.

Входящее сообщение `msg`:
{

"payload": 750,

"topic": "modbus/relay-module-1/ch-3/current"

}

Задача: Преобразовать `msg.payload` в следующий формат:
{

"value": 0.75,

"unit": "A",

"source": "relay-ch-3"

}

Решение с помощью ноды `Change`:
  • Добавьте ноду `Change` в поток.
  • В правилах выберите "set" (`установить`).
  • В поле "to the value" (`в значение`) выберите тип `J:` (JSONata Expression).
  • Введите следующее выражение в текстовое поле:
  • {
    

    "value": payload / 1000,

    "unit": "A",

    "source": "relay-ch-3"

    }

    Как это работает:

    Пример 2: Сложная маршрутизация в ноде `Switch`

    Стандартные правила ноды `Switch` позволяют проверять одно условие за раз. Но что, если нам нужно принять решение на основе комбинации нескольких факторов? Например, включить принудительную вентиляцию в помещении, только если температура превысила 25°C И уровень CO₂ превысил 1000 ppm.

    Входящее сообщение `msg` от мультисенсора:
    {
    

    "payload": {

    "temperature": 26.1,

    "humidity": 55,

    "co2": 1150

    }

    }

    Задача: Пропустить сообщение дальше по потоку только если `temperature > 25` И `co2 > 1000`. Решение с помощью ноды `Switch`:
  • Добавьте ноду `Switch` в поток.
  • В правиле проверки вместо `payload` выберите тип `J:` (JSONata Expression).
  • Введите следующее выражение:
  • `payload.temperature > 25 and payload.co2 > 1000`

  • В качестве оператора сравнения справа от выражения выберите `is true`.
  • Как это работает:

    Эти два примера демонстрируют, как JSONata позволяет инкапсулировать сложную логику преобразования и маршрутизации внутри одной ноды, делая потоки более компактными, читаемыми и эффективными.

    ---

    Базовые операторы и выражения

    Мы уже коснулись некоторых операторов в предыдущих примерах. Теперь давайте систематизируем основные строительные блоки, из которых состоят JSONata-выражения.

    > ⚠️ Внимание: JSONata строго типизирован в вопросах истинности (truthiness). Пустая строка `''`, число `0`, пустой массив `[]` и пустой объект `{}` считаются ложными (`false`). Любая непустая строка (даже `"false"` или `"0"`), любое ненулевое число и любой непустой объект/массив считаются истинными (`true`). Будьте внимательны при проверке небулевых значений в условных выражениях.

    Арифметические операторы

    JSONata поддерживает стандартный набор арифметических операторов для работы с числами.

    `` (умножение) Пример: Преобразование температуры из Цельсия в Фаренгейты. Выражение в ноде `Change` (для установки `msg.fahrenheit`): `payload.value 1.8 + 32`

    Строковая конкатенация

    Для объединения (конкатенации) строк используется оператор амперсанда `&`. Это полезно для формирования логов, уведомлений или динамических топиков MQTT.

    Пример: Создание человекочитаемого сообщения для лога.

    Обратите внимание, что числа автоматически преобразуются в строки при конкатенации.

    `'Value: ' & 100` -> `"Value: 100"`

    Операторы сравнения

    Операторы сравнения возвращают булево значение (`true` или `false`) и являются основой для логики в ноде `Switch` или в условных выражениях.

    | Оператор | Описание | Пример |

    | :------- | :----------------- | :-------------------------- |

    | `==` | Равно | `payload.status == "OK"` |

    | `!=` | Не равно | `payload.errorCode != 0` |

    | `>` | Больше | `payload.temperature > 30` |

    | `<` | Меньше | `payload.voltage < 220` |

    | `>=` | Больше или равно | `payload.level >= 95` |

    | `<=` | Меньше или равно | `payload.pressure <= 1.5` |

    Булева логика

    Для комбинирования нескольких условий используются логические операторы `and` и `or`.

    Пример: Проверка критического состояния бойлера.

    Сочетая эти базовые операторы, вы уже можете строить довольно сложные и полезные выражения для обработки данных прямо в стандартных нодах, значительно сокращая потребность в написании кода.

    ---

    Итоги и следующие шаги

    В этом уроке мы сделали первый, но самый важный шаг в освоении JSONata — мощного инструмента для декларативной обработки данных в Node-RED.

    Мы выяснили, что JSONata — это, по сути, "SQL для JSON", позволяющий нам элегантно и эффективно запрашивать и трансформировать данные без использования ноды `Function` и JavaScript. Это делает потоки более читаемыми, надежными и доступными для инженеров с разным уровнем подготовки.

    Ключевые моменты, которые мы усвоили:

  • Назначение JSONata: Это язык выражений для манипуляции JSON-данными, интегрированный в ядро Node-RED для упрощения трансформаций и маршрутизации.
  • Базовый синтаксис: Мы научились извлекать данные из любой части объекта `msg`, используя точечную нотацию для простых свойств, квадратные скобки для индексов массивов и специальную скобочную нотацию для ключей с нестандартными символами.
  • Практическое применение: На примерах нод `Change` и `Switch` мы увидели, как JSONata позволяет динамически формировать новые структуры данных и создавать сложные, многофакторные правила маршрутизации.
  • Основные операторы: Мы познакомились с арифметическими, строковыми и логическими операторами, которые являются фундаментом для построения любых выражений.
  • JSONata — это не просто "синтаксический сахар", а фундаментальный навык для любого специалиста, работающего с Node-RED на профессиональном уровне. Он позволяет строить сложные и в то же время элегантные и поддерживаемые системы автоматизации.

    В следующем уроке мы углубимся в более продвинутые возможности JSONata. Мы рассмотрим:

    Эти знания позволят вам решать еще более широкий круг задач по обработке данных с максимальной эффективностью.