Fundamentals 7 min read

Why cJSON Is the Ideal Lightweight JSON Parser for Resource‑Constrained MCUs

This article introduces cJSON, a tiny open‑source C library designed for embedded systems, explains its core features, shows how to create, parse, and manipulate JSON data on microcontrollers, and provides practical code examples for configuration management, command handling, and data logging.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Why cJSON Is the Ideal Lightweight JSON Parser for Resource‑Constrained MCUs

cJSON is an ultra‑lightweight, pure‑C JSON parsing library consisting of a single .h and .c file, making it suitable for memory‑constrained microcontrollers such as STM32F103 or ESP8266.

Key Characteristics

Minimal memory footprint : parsing requires only a few kilobytes of RAM.

Pure C implementation : no third‑party dependencies; builds with Keil, IAR, GCC, etc.

Simple API : can be learned in minutes.

Flexible : supports dynamic creation, modification, serialization and deserialization of JSON objects.

GitHub repository: https://github.com/DaveGamble/cJSON

Basic Usage – Creating JSON

#include "cJSON.h"

void create_json(void) {
    // 1. Create root object
    cJSON *root = cJSON_CreateObject();
    // 2. Add key‑value pairs
    cJSON_AddStringToObject(root, "device", "ESP32");
    cJSON_AddNumberToObject(root, "temperature", 25.6);
    // 3. Add nested object
    cJSON *location = cJSON_CreateObject();
    cJSON_AddNumberToObject(location, "lat", 35.6895);
    cJSON_AddNumberToObject(location, "lon", 139.6917);
    cJSON_AddItemToObject(root, "location", location);
    // 4. Generate JSON string
    char *json_str = cJSON_Print(root);
    printf("JSON: %s
", json_str);
    // 5. Free resources
    free(json_str);
    cJSON_Delete(root);
}

Resulting JSON:

{
  "device": "ESP32",
  "temperature": 25.6,
  "location": {
    "lat": 35.6895,
    "lon": 139.6917
  }
}

Parsing JSON

void parse_json(const char *json_str) {
    cJSON *root = cJSON_Parse(json_str);
    if (root == NULL) {
        printf("JSON parsing failed!
");
        return;
    }
    cJSON *device = cJSON_GetObjectItem(root, "device");
    cJSON *temp   = cJSON_GetObjectItem(root, "temperature");
    cJSON *location = cJSON_GetObjectItem(root, "location");
    printf("Device: %s, Temp: %.1f
", device->valuestring, temp->valuedouble);
    printf("Lat/Lon: (%.4f, %.4f)
",
           cJSON_GetObjectItem(location, "lat")->valuedouble,
           cJSON_GetObjectItem(location, "lon")->valuedouble);
    cJSON_Delete(root);
}

Typical Embedded Use Cases

1. Dynamic Configuration Management

Store configuration in a JSON file and parse it at runtime, enabling OTA updates without recompiling.

// config.json
{
  "wifi": {"ssid": "MyIoT", "password": "123456"},
  "sampling_interval": 5000
}

void load_config(void) {
    char *json_str = read_file("config.json");
    cJSON *root = cJSON_Parse(json_str);
    cJSON *wifi = cJSON_GetObjectItem(root, "wifi");
    char *ssid = cJSON_GetObjectItem(wifi, "ssid")->valuestring;
    char *pwd  = cJSON_GetObjectItem(wifi, "password")->valuestring;
    int interval = cJSON_GetObjectItem(root, "sampling_interval")->valueint;
    printf("Wi‑Fi: %s/%s, Interval: %dms
", ssid, pwd, interval);
    cJSON_Delete(root);
    free(json_str);
}

2. Device‑to‑Device Communication Protocol

Use JSON commands for human‑readable, easily debuggable messaging.

void handle_command(const char *json_str) {
    cJSON *root = cJSON_Parse(json_str);
    const char *cmd = cJSON_GetObjectItem(root, "cmd")->valuestring;
    if (strcmp(cmd, "set_led") == 0) {
        cJSON *args = cJSON_GetObjectItem(root, "args");
        int id = cJSON_GetObjectItem(args, "id")->valueint;
        int brightness = cJSON_GetObjectItem(args, "brightness")->valueint;
        led_set(id, brightness);
    }
    cJSON_Delete(root);
}

3. Local Data Storage & Logging

Serialize sensor readings to JSON for plain‑text logs, simplifying later analysis.

void log_sensor_data(float temp, float humidity) {
    cJSON *root = cJSON_CreateObject();
    cJSON_AddNumberToObject(root, "temp", temp);
    cJSON_AddNumberToObject(root, "humidity", humidity);
    cJSON_AddStringToObject(root, "timestamp", "2023-08-15T14:30:00Z");
    char *json_str = cJSON_PrintUnformatted(root); // compact output
    write_to_sd_card("log.json", json_str);
    free(json_str);
    cJSON_Delete(root);
}

Practical Tips

Always call cJSON_Delete() and free() for allocated objects to avoid memory leaks.

Use short key names to reduce RAM usage and transmission bandwidth.

For large payloads, consider cJSON_ParseWithOpts for incremental parsing, which lowers peak memory consumption.

These techniques enable flexible, human‑readable configuration and communication on even the most memory‑constrained MCUs without sacrificing performance.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Configuration ManagementMicrocontrollerC libraryjson-parsingcJSONdata logging
Liangxu Linux
Written by

Liangxu Linux

Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.