Первую установку ArduinoJson я провёл по старинке: скачал zip с GitHub, распаковал в папку libraries — и месяц жил нормально, пока не скопировал в тот же каталог вторую версию от другого проекта. Две копии в библиотеках, файлы с одинаковыми именами, компилятор подхватил не ту — и я полвечера ловил загадочную ошибку в строке, которую не писал. Установка через менеджер библиотек заняла бы минуту и не оставила бы от этой истории и следа.
Урок, как всегда, двойной. Первый: ставьте библиотеки менеджером — он следит за версиями и не плодит копий. Второй: ArduinoJson — редкий случай, когда версия библиотеки видна в чужом коде невооружённым глазом: торчащий в скетче StaticJsonDocument — это шестая версия, вышедшая до января 2024 года. Седьмая переиначила главный класс, и в этом уроке мы разложим, что именно изменилось, чтобы чужие скетчи из интернета читались вами как переведённые, а не как иероглифы.
Разберём установку обоими путями — менеджером и в PlatformIO, соберём проверочный скетч на пять строк, пройдёмся по таблице отличий v6 и v7 и мигрируем старый код без правки логики. Синтаксис JSON мы уже знаем из первого урока раздела, так что скобки нас больше не пугают.
Установка: менеджер библиотек и PlatformIO
В Arduino IDE путь короткий: Tools — Manage Libraries, в поиске набираете ArduinoJson, автор — Benoit Blanchon, это важно, потому что в списке есть и клоны. Жмёте Install — и всё: менеджер скачивает архив, распаковывает его в папку libraries вашего sketchbook, каталога с проектами, и библиотека мгновенно видна всем скетчам на машине. Обновляется так же одной кнопкой, и перед кнопкой стоит прочитать, что меняется: между мажорными версиями бывают переименования. Мы ходили туда в уроке про менеджер библиотек и в обзоре работы с библиотеками в IDE — там и скриншоты, и грабли с правами на Windows.
PlatformIO живёт декларациями: в platformio.ini дописывается строка lib_deps = bblanchon/ArduinoJson@^7.4.2 — платформа сама скачает библиотеку при следующей сборке и прибьёт её к проекту. Циркумфлекс означает «седьмая или младше, но не восьмая»: проекты на PlatformIO живут годами, и такая запись спасает от неожиданного переезда на мажор со сломанной совместимостью. Для Arduino IDE тот же смысл достигается вручную: менеджер предложит обновление — читайте список изменений, прежде чем жать кнопку.
Проверка живости — одна минута: Файл — Примеры — ArduinoJson — там лежат готовые демо от автора. Но надёжнее собрать свой скетч из пяти строк: если он скомпилировался и напечатал значение — библиотека стоит, версия та, а среда собирает проекты с ней без вопросов. Вот он.
#include <ArduinoJson.h> JsonDocument doc; void setup() { Serial.begin(9600); deserializeJson(doc, "{\"temp\":21.4}"); float t = doc["temp"]; Serial.print("temp="); Serial.println(t);} void loop() {}Теперь о версиях. Шестая жила с 2018 года и породила море туториалов, форумных ответов и видеокурсов — весь интернет до 2024-го писал в двух классах: StaticJsonDocument<200> со статическим буфером и DynamicJsonDocument(200) с буфером в куче. Седьмая вышла 3 января 2024 года и слила оба класса в один JsonDocument: ёмкость задаётся больше не вами, документ растёт в куче по мере надобности. Логика автора проста: два класса и ручной подбор размера породили больше ошибок NoMemory, чем все остальные причины вместе взятые, — а один тип снимает вопрос в принципе. Читая чужой скетч, вы теперь смотрите на дату: до 2024-го — синтаксис v6, после — v7. Старые туториалы не бесполезны, они просто разговаривают на диалекте, который полезно уметь переводить.
Миграция старого скетча обычно безболезненна, потому что компилятор не ломает, а предупреждает: устаревшие имена в седьмой версии остались псевдонимами для совместимости — StaticJsonDocument<200> соберётся как JsonDocument, игнорируя размер в угловых скобках, но с warning'ом про deprecated. Значит, план такой: обновили библиотеку, собрали, прочитали список предупреждений, заменили имена, выдохнули. Логика разбора при этом не меняется вообще — мы убедимся в этом в симуляторе ниже.
Отдельное слово про память, без которой выбор версии не обсуждается: мы уже считали байты SRAM в уроке про PROGMEM и память — у Uno их 2 КБ, и шестая версия с ручной ёмкостью хотя бы давала план заранее. Седьмая берёт память из кучи порциями; на ESP32 с сотнями килобайт это невидимо, на Uno — компромисс, о котором честно поговорим в уроке про JsonDocument, где куча и рост разобраны по шагам.
| Вопрос | Версия 6 | Версия 7 |
|---|---|---|
| Типы документа | StaticJsonDocument и DynamicJsonDocument — два класса | JsonDocument — один класс |
| Ёмкость | Задаёте вы: в угловых скобках или в конструкторе | Растёт сама, память берётся из кучи |
| Старые имена в новом коде | Норма | Компилируются как псевдонимы, но с предупреждением об устаревании |
| Не хватило места | Ошибка NoMemory в результате разбора | Попытка дорастить в куче; NoMemory — когда куча кончилась |
| Подбор размера | Онлайн-ассистент считает байты за вас | Не нужен: размер подбирает сам документ |
Что изменилось в API: сброс документа и мелочи
Изменений в повседневном API немного, и это хорошая новость. Запись и чтение не тронуты: doc["temp"] = 21.4; кладёт значение, doc["temp"] — достаёт. serializeJson и deserializeJson на местах. Тонкость, о которой стоит знать заранее: deserializeJson перед разбором сбрасывает документ — старые ключи исчезают, документ пуст и заполняется заново. В шестой версии поведение было тем же, но молчало о себе в документации, и народ вдогонку вызывал clear() на всякий случай — иногда дважды, в двух местах скетча, потому что никто не помнил, кто из них уже почистил. В седьмой это задокументировано, и лишний clear() можно не писать: повторный разбор в тот же документ — штатная история для живой телеметрии.
Вторая тонкость — рост в куче. Документ, который в v6 вы ограничивали числом, теперь берёт память сам, и вы перестали видеть потолок: пока куча свободна, разбор пройдёт, как только закончилась — NoMemory. Это меняет характер ошибок: вместо «документ тесноват» вы получаете «куча кончилась», а это уже про весь проект, а не про одну строку. Мы детально разберём пул и рост в уроке про JsonDocument.
В симуляторе ниже — оба факта вживую. Один и тот же пакет в двух оформлениях: с переносами и пробелами против плотной строки — значения идентичны, потому что оформление в JSON не значимо. Затем повторный deserializeJson в тот же документ без clear(): свежий пакет приходит, старые ключи исчезают. Три пакета подряд — и вы видите, что документ живёт как почтовый ящик: пришло новое письмо, старое убрали. Чтение в сим-скетчах показано точечной формой doc.temp — на плате она равнозначна квадратным скобкам, а движок книги понимает только точку.
- Ставьте ArduinoJson менеджером библиотек или строкой lib_deps в PlatformIO — zip в папку libraries плодит дубли и конфликты
- Автор библиотеки — Benoit Blanchon; StaticJsonDocument в чужом коде — маркер версии 6, выпущенной до января 2024
- В v7 один JsonDocument вместо Static и Dynamic; старые имена компилируются как псевдонимы с предупреждением об устаревании
- deserializeJson сбрасывает документ перед разбором: повторный пакет в тот же doc — штатно, clear() не обязателен
- Проверка установки — пятистрочный скетч: разобрать строку, прочитать ключ, напечатать в Serial
- 1. Как задавалась ёмкость StaticJsonDocument в шестой версии?
- 2. Что делает deserializeJson с документом перед разбором?
- 3. Куда менеджер библиотек кладёт установленную библиотеку?
- 4. Старый скетч с DynamicJsonDocument doc(512); собрали с библиотекой v7. Что будет?
- 5. Почему старые туториалы полны StaticJsonDocument?
Домашнее задание с платой: поставьте библиотеку менеджером, соберите проверочный скетч из этого урока и добавьте в него печать ARDUINOJSON_VERSION — чтобы версия была перед глазами всякий раз, когда сверяетесь с документацией. Вторая часть задания — на глаза: откройте любой форумный ответ с ArduinoJson, найдите в коде StaticJsonDocument или DynamicJsonDocument и мысленно переведите на v7 по таблице выше; через десять таких переводов диалект перестанет узнаваться как чужой. Дальше по разделу спускаемся в недра нового класса: как JsonDocument растёт в куче, что с ним делать на Uno с её 2 КБ и почему о ёмкости можно забыть — JsonDocument: один тип вместо двух. А собранный здесь навык установки пригодится мгновенно: без библиотеки не соберётся ни один пример, включая публикацию телеметрии в MQTT, куда мы придём в конце раздела.
Частые вопросы по теме урока
- Как задавалась ёмкость StaticJsonDocument в шестой версии?
- У статического документа ёмкость сидела в угловых скобках шаблона, у динамического — в конструкторе. В v7 оба параметра упразднены. В угловых скобках шаблона: StaticJsonDocument<200>
- Что делает deserializeJson с документом перед разбором?
- Перед разбором документ очищается. Повторный deserializeJson в тот же doc — штатная замена почтового ящика: новое письмо, старое убрано. Сбрасывает его: старые ключи исчезают
- Куда менеджер библиотек кладёт установленную библиотеку?
- Sketchbook/libraries — общий склад библиотек всех проектов. Складывать копию библиотеки рядом со скетчем — путь к дубликатам и конфликтам. В папку libraries внутри sketchbook
- Старый скетч с DynamicJsonDocument doc(512); собрали с библиотекой v7. Что будет?
- Старые имена в v7 — псевдонимы совместимости: код собирается, компилятор предупреждает про deprecated. Размер в скобках игнорируется. Скомпилируется с предупреждением об устаревании
- Почему старые туториалы полны StaticJsonDocument?
- Датировка решает: всё, что написано до выхода v7, разговаривает диалектом v6. Перевод на новый синтаксис — замена имён, логика та же. Их писали для шестой версии до января 2024 года