Интересный материал, спасибо за ваш труд. Давненько планирую сделать небольшую open-source библиотеку для отслеживания выхода потоков за границы стека через MPU. Реализация будет на основе "жёлтой/красной" зоны и ротации регионов по таймеру (чтобы даже при ограниченном числе регионов успевать проверять разные стеки). При срабатывании библиотека будет вызывать коллбэк с информацией о нарушении, а дальше пользователь сам решает: логировать, перезапускать поток или падать в fault. Что скажете о такой реализации?
Формулировки из CISA это рекомендации и требования по roadmap’у безопасности, а не закон. Да, сейчас есть тренд в США и Европе на уход от memory-unsafe языков, особенно в критической инфраструктуре. Но прямого запрета на C/C++ нет, и он вряд ли будет потому как слишком много кода, драйверов и ядер написано именно на C.
Вот как раз эта боль и была одной из причин появления JsonX. cJSON сам по себе всегда строит полное дерево и делает динамические аллокации. На больших JSON это действительно может упереться в потолок кучи на ESP32 или MCU с меньшими ресурсами. JsonX эту проблему не убирает магией, но даёт контроль. Все аллокации идут через заданный механизм (ThreadX block pool, кастомный аллокатор для FreeRTOS или статический буфер в baremetal). Вы сами решаете, откуда брать память, и гарантированно освобождаете всё одним вызовом.
То есть если у вас формат заранее известен, можно ограничить использование кучи или полностью уйти от неё. А если JSON реально непредсказуемый и огромный, тогда да, придётся парсить дерево и держать его в памяти, тут JsonX тоже не спасёт.
Да, PB и SOAP отлично закрывают B2B-интеграции, в этом спору нет. Но статья изначально была не про это.
JsonX я задумывал именно как инструмент для локальной работы с JSON на MCU/RTOS, где формат уже выбран внешней системой или протоколом. Там задача не выбрать самый плотный формат передачи, а сделать жизнь разработчика проще: убрать боль с malloc/free, не писать тонну кода руками и при этом сохранить читаемость данных на этапе отладки.
Если проекту нужен Modbus или PB это правильный выбор для этого проекта. Но когда в системе уже есть JSON (а таких кейсов полно: конфиги, отчёты, API-шлюзы), то JsonX позволяет работать с ним предсказуемо и без геморроя на микроконтроллере.
Мы начали разговор про экономию памяти на MCU, а закончили обсуждением SOAP и enterprise-схем, это уже про совсем другой уровень задач. Мы тут всё-таки обсуждаем подход к JSON на микроконтроллерах. Сравнивать JSON c SOAP или gRPC - это уже другой класс задач: обмен в корпоративных системах и B2B. Там свои требования, но это не отменяет того факта, что на MCU JSON остаётся самым простым и читаемым вариантом. Вопрос "какой протокол лучше для enterprise" выходит за рамки - здесь речь идёт о том, как комфортно жить с JSON именно на контроллерах, где malloc/free превращаются в проблему, а разработчикам нужны удобные инструменты.
Если формат JSON меняется, код всё равно приходится обновлять. Разница лишь в подходе:
с jansson это новый сгенерированный/написанный код парсинга,
с JsonX — просто правка схемы JX_ELEMENT[] и точек, где реально используются новые поля.
То есть в JsonX меняешь декларативный шаблон, а не километры кода (пусть даже сгенерированного). Да и в git-коммитах это выглядит чище.
JsonX ещё добавляет толерантность к изменениям:
неизвестные ключи игнорируются автоматически
поля можно объявить optional с дефолтами
легко держать две версии схемы и выбирать их по version внутри JSON.
Это снижает риск сломаться при обновлении формата и делает цикл обновил -> пересобрал -> перепрошил короче и предсказуемее.
Повторное использование кода при множестве схем
В JsonX ядро парсинга/генерации общее: новые структуры = новые таблицы маппинга, без дублирования логики. В jansson (и подобных) для каждой схемы нужен свой код: либо ручной обход, либо отдельный десериализатор. В итоге каждая новая структура тянет за собой новый кусок боевого кода, который потом надо поддерживать.
Поэтому я и считаю, что JsonX экономит ресурсы: вместо того чтобы писать новый десериализатор, я переиспользую существующий механизм и просто добавляю схему.
Согласен, PB выигрывает и по плотности, и по совместимости это его сильная сторона. Если главная цель именно максимальная экономия трафика и байтов в хранилище, то тут спорить нечего, PB/nanopb логичнее.
Но JsonX решает другую боль:
не экономия ради экономии, а предсказуемая работа в ограниченной среде (RTOS, MCU без динамики, фиксированные схемы);
JSON остаётся читаемым и легко отлаживаемым прямо в логах или редакторе, без генерации .proto и тулов;
автоматический маппинг в структуры на C даёт быстрый результат без тонны ручного кода.
Поэтому я и позиционирую JsonX как рабочий компромисс: в закрытых протоколах удобнее битовые пакеты или PB, но как только нужна интеграция с внешними сервисами или читаемость на этапе отладки - JSON выигрывает.
В итоге всё сводится к тому, что инструмент подбирается под задачу: где-то PB, где-то JSON, где-то вообще свой бинарный формат.
Я тоже в своё время использовал JFES (и, кажется, тоже именно на Хабре впервые о ней узнал). Библиотека действительно хорошая и лёгкая. Но у неё есть свой минус — нет маппинга: после парсинга всё равно приходится руками разбирать дерево/токены и переносить данные в структуру. JsonX как раз родился как надстройка над cJSON именно ради этого: один раз описал схему JX_ELEMENT[] и дальше работаешь сразу со структурами, без километров кода для обхода.
Да, в маппинге JX_ELEMENT[] вы описываете только те поля, которые вам нужны. Если в JSON будут лишние ключи то они просто игнорируются. С вложенными объектами и массивами схема похожая: - Для объекта можно задать под-массив JX_ELEMENT[]и указать на него ссылку в описании. Тогда парсер зайдёт внутрь и распарсит только те поля, что вы описали. - Для массивов можно задать фиксированный размер и тип элементов. Например, массив чисел из 5 элементов или массив структур с под-описанием.
Пример здесь в комментах посмотрите. Я постарался в самой либе включить все кейсы. Если есть пример JSON могу помочь с его маппингом.
Да, вы правы - если смотреть только на экономию памяти, то дешевле всего гнать сырые структуры и напрямую писать/читать их из конфигов. Я об этом и упоминал во введении: это действительно самый лёгкий путь, не запрещено конституцией. Но на практике это не всегда удобно:
Отладка превращается в мучение, особенно когда структур много и они громоздкие. С JSON проще открыть лог, быстро глазами проверить поле или прогнать через любой редактор.
Масштабируемость: когда проект растёт и структур десятки, ручное копание в бинарных дампах начинает тормозить разработку.
JsonX родился именно как компромисс: память контролируется, но при этом сохраняется удобство работы с читаемым JSON и автоматический маппинг в структуры. А в итоге всё упирается в задачи: кому-то проще битовые пакеты, кому-то Protobuf, кому-то JSON. Тут как говорится, на вкус и цвет все фломастеры разные.
Автоматический mapping в JsonX это не "псевдоавтоматизм", а практический инструмент. Да, структура JSON должна быть известна заранее, и это абсолютно нормально для embedded-конфигов и отчётов: там всегда есть фиксированная схема. В таких случаях JX_ELEMENT[] позволяет один раз описать поля и больше не думать, как руками вытаскивать данные из дерева. Когда JSON реально неизвестной структуры - тогда, конечно, остаётся классический обход дерева. Но в индустриальных MCU/RTOS-проектах это скорее редкость: чаще работают с предсказуемыми форматами обмена, где как раз и нужен быстрый и безопасный маппинг. То есть JsonX и задумывался не как универсальный агент, а как практичное решение для конкретной задачи: работа с фиксированными JSON-схемами на микроконтроллерах с жёсткими ограничениями по памяти.
Claude и другие LLM-агенты действительно могут сымитировать парсинг/генерацию JSON или даже сгенерировать код для этого - у них в обучении было море примеров. Но это инструмент для разработчика, а не для встраиваемой системы. Эта библиотека не "понятна и доступна" для Claude по одной простой причине: у неё нет STL, шаблонов и типичных C++-механизмов, к которым модели привыкли. Это чистый C с ручным маппингом через JX_ELEMENT[]. Для агента это не очевидно: попробуйте скормить Claude саму либу и попросить сгенерировать пример работы - он скорее всего запутается в описании маппинга или выдаст "обычный" код на cJSON. JsonX как раз и нужен для того, чтобы убрать эту рутину на MCU.
Protocol Buffers/nanopb хороши, когда критична максимальная экономия байтов. Но у них минус - генерация кода и бинарный формат, который неудобно отлаживать. JsonX оставляет читаемый JSON и упрощает жизнь на MCU, где важен именно контроль памяти и маппинг в структуры.
Rust с serde - действительно мощная связка, но она уместна там, где есть ресурсы и готовность строить весь проект вокруг Rust. На embedded-рынке это пока очень нишевая история. Большинство реальных промышленных проектов до сих пор пишется на C, и часто в условиях, где Rust просто не вариант (отсутствие toolchain’а, строгие требования к сертификации, ограниченные MCU).
JsonX как раз и родился из практики: "староверы на C" сталкиваются не с отсутствием JSON, а с болью интеграции его в RTOS-среды с контролем памяти. И тут как раз нужна лёгкая обёртка, а не «своя кривоватая реализация».
Размер кода: сам JsonX + cJSON в сборке под STM32H7 занимают порядка 10–12 КБ в ROM + ваш mapping. JsonX добавляет буквально сотни байт сверху cJSON.
Память: В baremetal-режиме можно работать полностью без кучи, только со статическим пулом (размер задаёте сами). В RTOS-режиме (ThreadX/FreeRTOS) аллокации идут через системный или кастомный allocator. В типовом примере JSON-конфига на ~500 байт суммарные выделения - до 2-3 КБ во время парсинга, после jx_free() память полностью освобождается.
Стек: функции не используют больших временных буферов, нагрузка минимальна (~200–300 байт).
Время: на STM32H753 (Cortex-M7, 400 МГц) парсинг JSON-строки размером ~1 КБ занимает <1 мс, генерация сопоставимого по размеру JSON - тоже в районе миллисекунды.
JsonX не претендует на рекорды по скорости - это по сути thin-layer над cJSON. Основная цель: предсказуемость и контроль памяти, чтобы не было скрытых malloc/free и утечек.
Под "контролируемой работой с памятью" я имел в виду не то, что JsonX волшебным образом убирает динамику, а то, что все выделения идут через заранее определённый механизм. Это может быть пул в ThreadX, безопасный аллокатор для FreeRTOS или статический буфер в baremetal. То есть разработчик сам решает, откуда брать память, и она не "разъезжается" по куче.
Да, если JSON заранее неизвестной структуры, то дерево всё равно строится. Но JsonX позволяет хотя бы держать это дерево в предсказуемых границах, и освобождается оно единым вызовом — без риска потерять куски.
Согласен, что мьютекс решает вопросы многопоточности при malloc. Но на длинных аптаймах фрагментация и непредсказуемые провалы при аллокации могут быть куда болезненнее, чем гонки за mutex. В enterprise-системах это особенно критично, и именно поэтому я старался уйти от кучи и сделать работу предсказуемой.
Jansson знаю и сам пробовал - отличная библиотека, но она работает только с деревом JSON-объектов. Автоматического маппинга в структуры у неё нет: значения всё равно приходится доставать вручную и переносить в поля. JsonX же изначально задумывался именно под MCU и RTOS, где важны минимализм, предсказуемость и возможность описать схему один раз через JX_ELEMENT[], а дальше работать со структурами напрямую.
Все эти преимущества сложно оценить, если вы сами не сталкивались с ограничениями MCU и RTOS, где каждая утечка или лишний malloc могут стоить стабильности системы.
Спасибо за ваш интерес и детальный обзор других JSON-библиотек. Да, большинство библиотек из списка я знаю и пробовал. ArduinoJson, JSMN, jansson - все они хороши в своих нишах, ArduinoJson например действительно очень удобна на Arduino/ESP, у нее шикарная документация и примеры. Но JsonX решает чуть другую задачу:
не пытается конкурировать с ArduinoJson или jansson, а именно дополняет cJSON.
Я делал JsonX в первую очередь для проектов на STM32 + RTOS, где хотелось иметь жесткий контроль над памятью (пул ThreadX, кастомные аллокаторы для FreeRTOS, статический буфер в baremetal). Это даёт предсказуемость и стабильность.
Многие популярные JSON-библиотеки делают ставку на C++ и естественно используют кучу. В C++ реализовать маппинг JSON структура относительно просто: есть шаблоны, STL и прочая "тяжёлая артиллерия". А вот в чистом C это боль и грабли с топором на конце. Если библиотека написана на C, то: как правило, она ограничивается только парсингом JSON. Дальше разработчику приходится вручную обходить дерево или токены и самому переносить данные в структуру. JsonX решает эту проблему: он даёт именно автоматический маппинг JSON <> C-структуры через JX_ELEMENT[]. То есть схема описывается один раз, а дальше можно работать напрямую со структурами, без километров шаблонного кода.
USB 1 и отсутствие дров под них
Интересный материал, спасибо за ваш труд. Давненько планирую сделать небольшую open-source библиотеку для отслеживания выхода потоков за границы стека через MPU. Реализация будет на основе "жёлтой/красной" зоны и ротации регионов по таймеру (чтобы даже при ограниченном числе регионов успевать проверять разные стеки). При срабатывании библиотека будет вызывать коллбэк с информацией о нарушении, а дальше пользователь сам решает: логировать, перезапускать поток или падать в fault. Что скажете о такой реализации?
Формулировки из CISA это рекомендации и требования по roadmap’у безопасности, а не закон. Да, сейчас есть тренд в США и Европе на уход от memory-unsafe языков, особенно в критической инфраструктуре. Но прямого запрета на C/C++ нет, и он вряд ли будет потому как слишком много кода, драйверов и ядер написано именно на C.
Вы прям заинтриговали меня. А можно ссылочку на закон, где это официально прописано?
Если сможете, буду признателен, интересно разобраться.
Вот как раз эта боль и была одной из причин появления JsonX.
cJSON сам по себе всегда строит полное дерево и делает динамические аллокации. На больших JSON это действительно может упереться в потолок кучи на ESP32 или MCU с меньшими ресурсами.
JsonX эту проблему не убирает магией, но даёт контроль. Все аллокации идут через заданный механизм (ThreadX block pool, кастомный аллокатор для FreeRTOS или статический буфер в baremetal). Вы сами решаете, откуда брать память, и гарантированно освобождаете всё одним вызовом.
То есть если у вас формат заранее известен, можно ограничить использование кучи или полностью уйти от неё. А если JSON реально непредсказуемый и огромный, тогда да, придётся парсить дерево и держать его в памяти, тут JsonX тоже не спасёт.
Да, PB и SOAP отлично закрывают B2B-интеграции, в этом спору нет. Но статья изначально была не про это.
JsonX я задумывал именно как инструмент для локальной работы с JSON на MCU/RTOS, где формат уже выбран внешней системой или протоколом. Там задача не выбрать самый плотный формат передачи, а сделать жизнь разработчика проще: убрать боль с malloc/free, не писать тонну кода руками и при этом сохранить читаемость данных на этапе отладки.
Если проекту нужен Modbus или PB это правильный выбор для этого проекта. Но когда в системе уже есть JSON (а таких кейсов полно: конфиги, отчёты, API-шлюзы), то JsonX позволяет работать с ним предсказуемо и без геморроя на микроконтроллере.
Мы начали разговор про экономию памяти на MCU, а закончили обсуждением SOAP и enterprise-схем, это уже про совсем другой уровень задач.
Мы тут всё-таки обсуждаем подход к JSON на микроконтроллерах. Сравнивать JSON c SOAP или gRPC - это уже другой класс задач: обмен в корпоративных системах и B2B. Там свои требования, но это не отменяет того факта, что на MCU JSON остаётся самым простым и читаемым вариантом.
Вопрос "какой протокол лучше для enterprise" выходит за рамки - здесь речь идёт о том, как комфортно жить с JSON именно на контроллерах, где malloc/free превращаются в проблему, а разработчикам нужны удобные инструменты.
Если формат JSON меняется, код всё равно приходится обновлять. Разница лишь в подходе:
с jansson это новый сгенерированный/написанный код парсинга,
с JsonX — просто правка схемы JX_ELEMENT[] и точек, где реально используются новые поля.
То есть в JsonX меняешь декларативный шаблон, а не километры кода (пусть даже сгенерированного). Да и в git-коммитах это выглядит чище.
JsonX ещё добавляет толерантность к изменениям:
неизвестные ключи игнорируются автоматически
поля можно объявить optional с дефолтами
легко держать две версии схемы и выбирать их по version внутри JSON.
Это снижает риск сломаться при обновлении формата и делает цикл обновил -> пересобрал -> перепрошил короче и предсказуемее.
Повторное использование кода при множестве схем
В JsonX ядро парсинга/генерации общее: новые структуры = новые таблицы маппинга, без дублирования логики.
В jansson (и подобных) для каждой схемы нужен свой код: либо ручной обход, либо отдельный десериализатор. В итоге каждая новая структура тянет за собой новый кусок боевого кода, который потом надо поддерживать.
Поэтому я и считаю, что JsonX экономит ресурсы: вместо того чтобы писать новый десериализатор, я переиспользую существующий механизм и просто добавляю схему.
Согласен, PB выигрывает и по плотности, и по совместимости это его сильная сторона. Если главная цель именно максимальная экономия трафика и байтов в хранилище, то тут спорить нечего, PB/nanopb логичнее.
Но JsonX решает другую боль:
не экономия ради экономии, а предсказуемая работа в ограниченной среде (RTOS, MCU без динамики, фиксированные схемы);
JSON остаётся читаемым и легко отлаживаемым прямо в логах или редакторе, без генерации .proto и тулов;
автоматический маппинг в структуры на C даёт быстрый результат без тонны ручного кода.
Поэтому я и позиционирую JsonX как рабочий компромисс: в закрытых протоколах удобнее битовые пакеты или PB, но как только нужна интеграция с внешними сервисами или читаемость на этапе отладки - JSON выигрывает.
В итоге всё сводится к тому, что инструмент подбирается под задачу: где-то PB, где-то JSON, где-то вообще свой бинарный формат.
Я тоже в своё время использовал JFES (и, кажется, тоже именно на Хабре впервые о ней узнал).
Библиотека действительно хорошая и лёгкая. Но у неё есть свой минус — нет маппинга: после парсинга всё равно приходится руками разбирать дерево/токены и переносить данные в структуру.
JsonX как раз родился как надстройка над cJSON именно ради этого: один раз описал схему
JX_ELEMENT[]
и дальше работаешь сразу со структурами, без километров кода для обхода.Да, в маппинге
JX_ELEMENT[]
вы описываете только те поля, которые вам нужны. Если в JSON будут лишние ключи то они просто игнорируются.С вложенными объектами и массивами схема похожая:
- Для объекта можно задать под-массив
JX_ELEMENT[]
и указать на него ссылку в описании. Тогда парсер зайдёт внутрь и распарсит только те поля, что вы описали.- Для массивов можно задать фиксированный размер и тип элементов. Например, массив чисел из 5 элементов или массив структур с под-описанием.
Пример здесь в комментах посмотрите. Я постарался в самой либе включить все кейсы. Если есть пример JSON могу помочь с его маппингом.
Да, вы правы - если смотреть только на экономию памяти, то дешевле всего гнать сырые структуры и напрямую писать/читать их из конфигов. Я об этом и упоминал во введении: это действительно самый лёгкий путь, не запрещено конституцией.
Но на практике это не всегда удобно:
Отладка превращается в мучение, особенно когда структур много и они громоздкие. С JSON проще открыть лог, быстро глазами проверить поле или прогнать через любой редактор.
Масштабируемость: когда проект растёт и структур десятки, ручное копание в бинарных дампах начинает тормозить разработку.
JsonX родился именно как компромисс: память контролируется, но при этом сохраняется удобство работы с читаемым JSON и автоматический маппинг в структуры.
А в итоге всё упирается в задачи: кому-то проще битовые пакеты, кому-то Protobuf, кому-то JSON. Тут как говорится, на вкус и цвет все фломастеры разные.
Автоматический mapping в JsonX это не "псевдоавтоматизм", а практический инструмент. Да, структура JSON должна быть известна заранее, и это абсолютно нормально для embedded-конфигов и отчётов: там всегда есть фиксированная схема. В таких случаях
JX_ELEMENT[]
позволяет один раз описать поля и больше не думать, как руками вытаскивать данные из дерева.Когда JSON реально неизвестной структуры - тогда, конечно, остаётся классический обход дерева. Но в индустриальных MCU/RTOS-проектах это скорее редкость: чаще работают с предсказуемыми форматами обмена, где как раз и нужен быстрый и безопасный маппинг. То есть JsonX и задумывался не как универсальный агент, а как практичное решение для конкретной задачи: работа с фиксированными JSON-схемами на микроконтроллерах с жёсткими ограничениями по памяти.
Claude и другие LLM-агенты действительно могут сымитировать парсинг/генерацию JSON или даже сгенерировать код для этого - у них в обучении было море примеров. Но это инструмент для разработчика, а не для встраиваемой системы.
Эта библиотека не "понятна и доступна" для Claude по одной простой причине: у неё нет STL, шаблонов и типичных C++-механизмов, к которым модели привыкли. Это чистый C с ручным маппингом через
JX_ELEMENT[]
. Для агента это не очевидно: попробуйте скормить Claude саму либу и попросить сгенерировать пример работы - он скорее всего запутается в описании маппинга или выдаст "обычный" код на cJSON. JsonX как раз и нужен для того, чтобы убрать эту рутину на MCU.Protocol Buffers/nanopb хороши, когда критична максимальная экономия байтов. Но у них минус - генерация кода и бинарный формат, который неудобно отлаживать. JsonX оставляет читаемый JSON и упрощает жизнь на MCU, где важен именно контроль памяти и маппинг в структуры.
Rust с serde - действительно мощная связка, но она уместна там, где есть ресурсы и готовность строить весь проект вокруг Rust. На embedded-рынке это пока очень нишевая история. Большинство реальных промышленных проектов до сих пор пишется на C, и часто в условиях, где Rust просто не вариант (отсутствие toolchain’а, строгие требования к сертификации, ограниченные MCU).
JsonX как раз и родился из практики: "староверы на C" сталкиваются не с отсутствием JSON, а с болью интеграции его в RTOS-среды с контролем памяти. И тут как раз нужна лёгкая обёртка, а не «своя кривоватая реализация».
JsonX по фактам:
Размер кода: сам JsonX + cJSON в сборке под STM32H7 занимают порядка 10–12 КБ в ROM + ваш mapping. JsonX добавляет буквально сотни байт сверху cJSON.
Память:
В baremetal-режиме можно работать полностью без кучи, только со статическим пулом (размер задаёте сами).
В RTOS-режиме (ThreadX/FreeRTOS) аллокации идут через системный или кастомный allocator. В типовом примере JSON-конфига на ~500 байт суммарные выделения - до 2-3 КБ во время парсинга, после jx_free() память полностью освобождается.
Стек: функции не используют больших временных буферов, нагрузка минимальна (~200–300 байт).
Время: на STM32H753 (Cortex-M7, 400 МГц) парсинг JSON-строки размером ~1 КБ занимает <1 мс, генерация сопоставимого по размеру JSON - тоже в районе миллисекунды.
JsonX не претендует на рекорды по скорости - это по сути thin-layer над cJSON. Основная цель: предсказуемость и контроль памяти, чтобы не было скрытых malloc/free и утечек.
Под "контролируемой работой с памятью" я имел в виду не то, что JsonX волшебным образом убирает динамику, а то, что все выделения идут через заранее определённый механизм. Это может быть пул в ThreadX, безопасный аллокатор для FreeRTOS или статический буфер в baremetal. То есть разработчик сам решает, откуда брать память, и она не "разъезжается" по куче.
Да, если JSON заранее неизвестной структуры, то дерево всё равно строится. Но JsonX позволяет хотя бы держать это дерево в предсказуемых границах, и освобождается оно единым вызовом — без риска потерять куски.
Согласен, что мьютекс решает вопросы многопоточности при malloc. Но на длинных аптаймах фрагментация и непредсказуемые провалы при аллокации могут быть куда болезненнее, чем гонки за mutex. В enterprise-системах это особенно критично, и именно поэтому я старался уйти от кучи и сделать работу предсказуемой.
Jansson знаю и сам пробовал - отличная библиотека, но она работает только с деревом JSON-объектов. Автоматического маппинга в структуры у неё нет: значения всё равно приходится доставать вручную и переносить в поля. JsonX же изначально задумывался именно под MCU и RTOS, где важны минимализм, предсказуемость и возможность описать схему один раз через
JX_ELEMENT[]
, а дальше работать со структурами напрямую.Все эти преимущества сложно оценить, если вы сами не сталкивались с ограничениями MCU и RTOS, где каждая утечка или лишний malloc могут стоить стабильности системы.
Да, JSMN тоже нравится, но в JsonX я сразу хотел уйти дальше простого парсинга и добавить маппинг структур + контроль памяти.
Спасибо за ваш интерес и детальный обзор других JSON-библиотек.
Да, большинство библиотек из списка я знаю и пробовал. ArduinoJson, JSMN, jansson - все они хороши в своих нишах, ArduinoJson например действительно очень удобна на Arduino/ESP, у нее шикарная документация и примеры.
Но JsonX решает чуть другую задачу:
не пытается конкурировать с ArduinoJson или jansson, а именно дополняет cJSON.
Я делал JsonX в первую очередь для проектов на STM32 + RTOS, где хотелось иметь жесткий контроль над памятью (пул ThreadX, кастомные аллокаторы для FreeRTOS, статический буфер в baremetal). Это даёт предсказуемость и стабильность.
Многие популярные JSON-библиотеки делают ставку на C++ и естественно используют кучу. В C++ реализовать маппинг JSON структура относительно просто: есть шаблоны, STL и прочая "тяжёлая артиллерия".
А вот в чистом C это боль и грабли с топором на конце. Если библиотека написана на C, то: как правило, она ограничивается только парсингом JSON. Дальше разработчику приходится вручную обходить дерево или токены и самому переносить данные в структуру. JsonX решает эту проблему: он даёт именно автоматический маппинг JSON <> C-структуры через
JX_ELEMENT[]
. То есть схема описывается один раз, а дальше можно работать напрямую со структурами, без километров шаблонного кода.255 это максимальное значение, а значений 256 так как 0 тоже значение