- PVSM.RU - https://www.pvsm.ru -
JSON сейчас встречается буквально везде - от веб-сервисов до IoT, но есть нюанс: почти все популярные JSON-библиотеки писались с расчётом на десктопы и серверы, где оперативку никто не считает по килобайтам. А вот на микроконтроллерах, особенно Cortex-M, каждый байт на счету. Да, конечно, можно гонять сырые структуры и их же писать в конфиг-файл, это как говорится "не запрещено конституцией". Но отладка в таком случае превращается в отдельный квест. В какой-то момент я понял, что мне надоело вручную возиться с JSON на микроконтроллерах: писать километры кода для обхода дерева cJSON [1], ловить утечки и гадать, где malloc снова подставит. Из всех этих соображений и родился JsonX [2] — лёгкая и минималистичная надстройка над cJSON, которую я делал в первую очередь под микроконтроллеры.
Преимущество JsonX:
удобный маппинг JSON <> C-структуры через плоское описание JX_ELEMENT[]
возможность работать полностью без динамических аллокаций (baremetal) или через системные аллокаторы (ThreadX / FreeRTOS)
простая конфигурация через jx_config.h [3]
и, самое важное, простая сериализация / десериализация C-структур
Хотя cJSON внутри парсит JSON в классическое дерево указателей, JsonX дополняет этот процесс плоским массивом элементов JX_ELEMENT[] [4], который используется для автоматического маппинга на поля вашей структуры. Схема данных JX_ELEMENT[] описывается плоско и заранее.
typedef struct
{
char property[JX_PROPERTY_MAX_SIZE];
JX_ELEMENT_TYPE type;
uint8_t value_len;
const void value_p;
JX_ELEMENT_STATUS status;
struct json_element_s element;
uint16_t element_size;
} JX_ELEMENT;
Это нам даёт:
Контролируемая работа с памятью: хотя cJSON внутри всё ещё строит дерево и делает аллокации, JsonX изолирует их в заданном аллокаторе и гарантирует корректное освобождение без утечек.
Структура конфигурации:
typedef struct
{
char device_name[32];
uint32_t baudrate;
bool debug;
} config_t;
config_t config;
Описание маппинга:
JX_ELEMENT config_desc[] =
{
JX_PROPERTY_STRING("device_name", config.device_name),
JX_PROPERTY_NUMBER("baudrate", config.baudrate),
JX_PROPERTY_BOOLEAN("debug", config.debug),
};
const size_t config_desc_size = sizeof(config_desc)/sizeof(config_desc[0]);
Парсинг JSON:
const char *config_json_str = "{"device_name":"sensor1","baudrate":9600,"debug":true}";
if(jx_json_to_struct(char *buffer, config_desc, config_desc_size, JX_MODE_STRICT) == JX_SUCCESS)
{
jx_log("Конфиг загружен: %s @ %lun", config.device_name, config.baudrate);
}
Генерация JSON:
char buffer[256];
jx_struct_to_json(config_desc, config_desc_size, buffer, sizeof(buffer), JX_FORMATTED);
jx_log("config: %srn", buffer);
JsonX можно собрать в одном из нескольких режимов:
ThreadX / FreeRTOS - с использованием системных аллокаторов
Baremetal - с собственным статическим пулом
Custom Allocators - использование полностью пользовательских функций выделения/освобождения памяти, переданных в JsonX (например, для POSIX или специфичных RTOS-аллокаторов)
Всё настраивается через jx_config.h [3] и флаги компиляции.
Все числа - пока double (как у cJSON). Планируется режим strict int
Максимальный размер имени поля задаётся макросом JX_PROPERTY_MAX_SIZE
Нет автоматического увеличения массива элементов - лимит задаётся заранее.
В текущей версии JsonX использует cJSON как движок парсинга и генерации. Однако в перспективе я рассматриваю вариант полного отказа от cJSON в пользу собственного парсера, который:
будет работать напрямую с заданным пулом памяти (например, block pool в ThreadX)
получит безопасный аллокатор для FreeRTOS с контролем границ и предотвращением фрагментации
сможет работать в полностью статическом режиме без единого вызова malloc/free
Снижение накладных расходов и позволит полностью исключить динамику при работе с JSON, если это критично для проекта
Окончательное решение будет зависеть от того, насколько библиотека будет востребована в сообществе и какие требования будут у пользователей. Если спрос на такую функциональность окажется высоким - развитие пойдёт в эту сторону
JsonX - это способ использовать cJSON в микроконтроллерах без непредсказуемых аллокаций и лишнего кода. Он особенно полезен там, где важно контролировать каждый байт и каждую миллисекунду, но при этом нужно работать с JSON так же удобно, как на ПК.
Репозиторий: JsonX [2]
Примеры - в файле: src/example.c [5]
Автор: mihailasd
Источник [6]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/json/431015
Ссылки в тексте:
[1] cJSON: https://github.com/DaveGamble/cJSON
[2] JsonX: https://github.com/embedmind/JsonX?tab=readme-ov-file
[3] jx_config.h: https://github.com/embedmind/JsonX/blob/main/inc/jx_config.h
[4] JX_ELEMENT[]: https://github.com/embedmind/JsonX/blob/main/inc/jx_types.h
[5] src/example.c: https://github.com/embedmind/JsonX/blob/main/src/example.c
[6] Источник: https://habr.com/ru/articles/948250/?utm_source=habrahabr&utm_medium=rss&utm_campaign=948250
Нажмите здесь для печати.