JsonDocument
Description
JsonDocument stores a JSON document in memory. It owns the memory referenced by JsonArray, JsonObject, and JsonVariant.
JsonDocument contains a fixed-size memory pool, with a monotonic allocator. This design allows ArduinoJson to be very efficient but requires some discipline on your side:
- Because the size is fixed, you need to specify the size when you create the
JsonDocument - Because the allocator is monotonic, it cannot release memory when you call
JsonObject::remove()for example.
I strongly recommend against using a global JsonDocument because you would be troubled by the monotonic allocator, and would make inefficient use of your RAM.
On the contrary, I recommend declaring a short-lived JsonDocument that you use only in your serialization functions.
For details on how to choose the right capacity for the JsonDocument, please read How to determine the capacity of the JsonDocument?
StaticJsonDocument vs DynamicJsonDocument
You can choose to store your JsonDocument in the stack or in the heap:
- Use a
StaticJsonDocumentto store in the stack (recommended for documents smaller than 1KB) - Use a
DynamicJsonDocumentto store in the heap (recommended for documents larger than 1KB)
You must specify the capacity of a StaticJsonDocument in a template parameter, like that:
StaticJsonDocument<256> doc;
For a DynamicJsonDocument, however, you must use a constructor argument:
DynamicJsonDocument doc(2048);
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
DynamicJsonDocument 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:
DynamicJsonDocument doc(1024);
doc["answer"] = 42;
// the doc contains {"answer":42}
Here is a JsonDocument that implicitly becomes an array:
DynamicJsonDocument doc(1024);
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>():
DynamicJsonDocument doc(1024);
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.
Member functions
as<T>()casts the root to the specified type (e.g.JsonArrayorJsonObject)add()adds elements to the root arraycapacity()returns the capacity of the memory poolclear()empties the document and resets the memory poolcontainsKey()tests if the root object contains the specified keycreateNestedArray()creates a nested array attached to the rootcreateNestedObject()create a nested object attached to the rootgarbageCollect()reclaims leaked memory blocksoperator[]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 emptymemoryUsage()tells how many bytes are used in the memory poolnesting()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()reduces the capacity of the memory pool to match the current usage*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.JsonArrayorJsonObject)
Example
Here is a program that deserializes a JSON document and stores it in the stack:
StaticJsonDocument<200> doc; // <- a little more than 200 bytes in the stack
char json[] = "{\"hello\":\"world\"}";
deserializeJson(doc, json);
const char* world = doc["hello"];
Here is a program that serializes a JSON document stored in the heap:
DynamicJsonDocument doc(200); // <- 200 bytes in the heap
doc["hello"] = "world";
serializeJson(doc, Serial); // {"hello":"world"}