The Terminology Trap: Elements vs. Members in ArduinoJson

When embedded developers search for Arduino JsonArray members, they are usually navigating a common semantic trap within the ArduinoJson library—the undisputed industry standard for MCU JSON parsing. In the strict terminology of the library's creator, Benoît Blanchon, a JsonArray contains elements (indexed values), while a JsonObject contains members (key-value pairs).

However, because modern IoT payloads heavily rely on arrays of objects (e.g., a list of sensor readings where each reading is an object with 'timestamp' and 'value' members), the search intent behind this phrase almost always targets how to access, iterate, and modify object members that reside within array elements. As of 2026, with ArduinoJson v7 fully established as the standard, the methods for handling these nested structures have been streamlined, but memory management on 8-bit and 32-bit microcontrollers remains a critical hurdle.

This quick reference guide and FAQ will clarify the terminology, provide exact code patterns for v7, and detail the SRAM limitations you must respect to prevent runtime crashes.

Quick Reference Matrix: JsonArray vs JsonObject

Before diving into the FAQs, review this structural comparison to ensure you are calling the correct methods on your JsonDocument nodes.

Operation JsonArray (Elements) JsonObject (Members)
Add Data arr.add(value) obj["key"] = value
Access Data arr[i] or arr.get<T>(i) obj["key"] or obj["key"].as<T>()
Iterate for (JsonVariant v : arr) for (JsonPair p : obj)
Count Items arr.size() obj.size()
Append Nested arr.add<JsonObject>() obj["key"].to<JsonArray>()

Frequently Asked Questions (FAQ)

1. How do I iterate through an array of objects and read their members?

In ArduinoJson v7, the JsonVariant class acts as a universal wrapper. To iterate through a JsonArray and access the members of the objects inside it, use a range-based for loop. This is highly memory-efficient as it avoids copying data.

// Assume 'doc' is your parsed JsonDocument
JsonArray sensorArray = doc["sensors"].as<JsonArray>();

for (JsonVariant element : sensorArray) {
  // 'element' is a JsonObject in this context
  const char* id = element["id"]; 
  float temp = element["temperature"]; // Reads the member
  Serial.printf("Sensor %s: %.2f C\n", id, temp);
}

Expert Tip: Always use .as<JsonArray>() when extracting the array from the root document to ensure type safety and prevent null-reference exceptions if the JSON payload is malformed.

2. How do I add a new object to an array and assign members to it?

In older versions (v6), developers used createNestedObject(). In ArduinoJson v7, the API is more intuitive and relies on template arguments. You append a new object to the array and immediately capture the reference to assign members.

JsonArray dataLog = doc["log"].to<JsonArray>();

// Append a new JsonObject and get its reference
JsonObject newEntry = dataLog.add<JsonObject>();
newEntry["timestamp"] = millis();
newEntry["status"] = "OK";
newEntry["voltage"] = 3.28;

3. What are the SRAM limits for JsonArrays on Uno R3 vs ESP32?

Memory management is where most MCU developers fail when handling JSON. ArduinoJson v7 introduced a unified JsonDocument that automatically allocates memory from the heap, but you are still bound by physical hardware limits.

  • Arduino Uno R3 / Nano (ATmega328P): Features only 2,048 bytes of SRAM. A safe JsonDocument limit is roughly 800 bytes. An array of objects will fill this instantly. Each JsonVariant node consumes 8 bytes of overhead. If you are parsing an array of 20 sensor readings, you will likely trigger an Out-Of-Memory (OOM) crash.
  • ESP32 (Standard): Features 520KB+ of SRAM. You can comfortably parse JSON payloads up to 50KB - 80KB. The node overhead is 16 bytes per element on this 32-bit architecture.
  • ESP32-S3 / Teensy 4.1 (with PSRAM): If you enable PSRAM support in the Arduino IDE, JsonDocument can expand into megabytes of external RAM, allowing you to parse massive REST API responses containing hundreds of array elements.

2026 Best Practice: Never hardcode massive JSON strings in your C++ sketch. Stream the JSON directly from WiFiClient or Serial into the deserializeJson() function to avoid duplicating the payload in SRAM before parsing. See the ArduinoJson V7 JsonDocument API for streaming deserialization examples.

4. How do I handle missing members inside an array element safely?

When dealing with unpredictable API responses, an array element might be missing a specific member. Accessing a missing member returns a null JsonVariant. You can use the isNull() method or provide default fallback values using the pipe | operator.

for (JsonVariant v : doc["devices"].as<JsonArray>()) {
  // Fallback to 0.0 if the "battery" member is missing
  float battery = v["battery"] | 0.0f; 
  
  // Fallback to "Unknown" if the "name" member is missing
  const char* name = v["name"] | "Unknown"; 
}

5. Can I modify an existing member inside an array element?

Yes. JsonDocument is entirely mutable. If you need to update a specific member within an array element (for example, toggling a boolean state before sending the JSON back to a server), you simply assign a new value to the key.

JsonArray relays = doc["relays"].as<JsonArray>();
// Update the 'state' member of the first element
relays[0]["state"] = true; 
relays[0]["lastToggle"] = 1715432100; // Unix timestamp

Troubleshooting Common Deserialization Failures

When parsing incoming JSON arrays, deserializeJson() may fail. Here is how to diagnose the specific DeserializationError codes related to arrays and members:

  1. NoMemory: Your JsonDocument ran out of heap space. This happens when the incoming array has more elements than the ESP32/Uno can track. Fix: Filter the JSON during deserialization using a JsonDocument filter to ignore unneeded array elements, or stream the data.
  2. InvalidInput: The JSON syntax is broken. A common cause is a missing comma between array elements (e.g., [{"a":1} {"b":2}]). Fix: Validate your payload with an external linter before debugging the MCU.
  3. EmptyInput: The serial buffer or HTTP client timed out before sending data. Fix: Ensure your network client has a proper timeout and that you are checking client.available() before parsing.

Advanced Edge Case: String Deduplication in Arrays

If your JsonArray contains multiple objects that share the exact same string values for certain members (e.g., an array of 100 temperature readings where the "unit" member is always "Celsius"), ArduinoJson v7 automatically performs string deduplication. It stores the string "Celsius" in the memory pool only once, and all 100 array elements point to that single memory address. This drastically reduces the SRAM footprint of repetitive IoT payloads. For a deeper dive into memory pooling mechanics, consult the ArduinoJson V7 JsonArray API documentation and the official GitHub repository.

Summary

While the phrase 'Arduino JsonArray members' technically mixes two distinct JSON concepts, the practical application—manipulating key-value pairs nested inside indexed arrays—is a daily reality for firmware engineers. By leveraging ArduinoJson v7's unified JsonDocument, utilizing range-based iteration, and respecting the strict SRAM ceilings of your target microcontroller, you can build robust, crash-free IoT data pipelines.