Here is the canonical example for serializing and deserializing with ArduinoJson.

By following this example, you are making the best use of your memory, and you maintain a good software design.

struct SensorData {
   const char* name;
   int time;
   float value;
};

#define SENSORDATA_JSON_SIZE (JSON_OBJECT_SIZE(3))

bool deserialize(SensorData& data, char* json)
{
    StaticJsonBuffer<SENSORDATA_JSON_SIZE> jsonBuffer;
    JsonObject& root = jsonBuffer.parseObject(json);
    data.name = root["name"];
    data.time = root["time"];
    data.value = root["value"];
    return root.success();
}

void serialize(const SensorData& data, char* json, size_t maxSize)
{
    StaticJsonBuffer<SENSORDATA_JSON_SIZE> jsonBuffer;
    JsonObject& root = jsonBuffer.createObject();
    root["name"] = data.name;
    root["time"] = data.time;
    root["value"] = data.value;
    root.printTo(json, maxSize);
}

As you can see the StaticJsonBuffer is kept in memory as short as possible, so that the remain of your program is unaffected by the JSON serialization.

Also you can see that neither JsonArray nor JsonObject leak out of the serialization code. This pattern maintains a good isolation and reduce the coupling with the library.

Where to go next?

Mastering ArduinoJson

If you are interested in writing good code and make the best possible use of the library, be sure to check Mastering ArduinoJson.

The last chapter contains several “case studies” that show practical examples of how to use ArduinoJson in the following contexts:

  • JSON configuration file on SPIFFS
  • Parsing weather forecast from OpenWeatherMap and Weather Underground
  • JSON-RPC

In each case, you’ll see that memory usage is very limited and that none of the programs uses a global JsonBuffer.