JsonDocument
Description
JsonDocument
stores a JSON document in memory. It owns the memory referenced by JsonArray
, JsonObject
, and JsonVariant
.
JsonDocument
vs JsonVariant
JsonDocument
shares many features with JsonVariant
; however, there is one big difference: JsonDocument
has value semantics, whereas JsonVariant
has reference semantics.
On the one hand, because JsonDocument
owns the data, if you copy a JsonDocument
, you get a complete clone.
// make a clone of the JsonDocument
JsonDocument doc2 = doc1;
On the other hand, because JsonVariant
is a reference, if you copy a JsonVariant
, you only clone the reference:
// make a new reference to the same variant
JsonVariant var2 = var1;
Using a JsonDocument
When you create a JsonDocument
, it is initially empty. At this stage, it’s neither an object, nor an array, and JsonDocument::isNull()
returns true
.
When you insert the first value in the JsonDocument
, it automatically changes its type to match the call. If you use the JsonDocument
like an array, it becomes an array; if you use the JsonDocument
as an object, it becomes an object.
Here is a JsonDocument
that implicitly becomes an object:
JsonDocument doc;
doc["answer"] = 42;
// the doc contains {"answer":42}
Here is a JsonDocument
that implicitly becomes an array:
JsonDocument doc;
doc.add(42);
// the doc contains [42]
Sometimes, however, you’ll need to explicitly convert the JsonDocument
without adding a value; for example, because you want to create an empty object. In this case you can call JsonDocument::to<T>()
:
JsonDocument doc;
JsonObject obj = doc.to<JsonObject>();
// the doc contains {}
JsonDocument::to<T>()
clears the document and converts it to the specified type. Don’t confuse this function with JsonDocument::as<T>()
that returns a reference only if the requested type matches the one in the document.
Allocator
By default, JsonDocument
allocates memory through the standard malloc()
and free()
functions. You can customize this behavior by providing a custom allocator to the constructor.
You create an allocator class by inheriting from ArduinoJson::Allocator
and implementing the pure virtual functions:
namespace ArduinoJson {
class Allocator {
public:
virtual void* allocate(size_t size) = 0;
virtual void deallocate(void* pointer) = 0;
virtual void* reallocate(void* pointer, size_t new_size) = 0;
};
}
For example, here is an allocator that uses ESP32’s capabilities-based heap memory allocator:
struct SpiRamAllocator : ArduinoJson::Allocator {
void* allocate(size_t size) override {
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
}
void deallocate(void* pointer) override {
heap_caps_free(pointer);
}
void* reallocate(void* ptr, size_t new_size) override {
return heap_caps_realloc(ptr, new_size, MALLOC_CAP_SPIRAM);
}
};
Then you must pass an instance of this class to the constructor of JsonDocument
:
SpiRamAllocator allocator;
JsonDocument doc(&allocator);
Member functions
as<T>()
casts the root to the specified type (e.g.JsonArray
orJsonObject
)add()
adds elements to the root arrayclear()
empties the document and resets the memory pool(deprecated)containsKey()
tests if the root object contains the specified keyoperator[]
gets or sets values in the documentoverflowed()
tells if the memory pool was large enoughis<T>()
tests the type of the rootisNull()
tells if the document is null or emptynesting()
returns the number of nesting layers in the documentremove()
removes an element (or member) at the specified index (or key)set()
replaces the root with the specified valueshrinkToFit()
release overallocated memory.size()
returns the number of elements (or members) that the root array (or object) containsto<T>()
clears the document and converts it to the specified type (e.g.JsonArray
orJsonObject
)
Example
JsonDocument doc;
doc["hello"] = "world";
serializeJson(doc, Serial); // {"hello":"world"}