ArduinoJson 6.17: save up to 332 bytes of RAM!
19 October 2020
I published a new version of ArduinoJson. No important feature this time, ArduinoJson 6.17 is more of a service pack.
As you’ll see, I managed to move some static data to Flash (i.e., PROGMEM
), saving a significant amount of memory on Harvard architectures (mainly AVR and ESP8266).
Unfortunately, this change has no impact on von Neumann architectures (such as ESP32, megaAVR, and ARM).
Errors strings moved to Flash
The first things I moved from RAM to Flash are the error strings.
DeserializationError
now supports a new member function f_str()
, which returns a const __FlashStringHelper*
(i.e., a Flash string with a recognisable type).
To use it, simply replace c_str
with f_str
, like so:
DeserializationError error = deserializeJson(doc, json);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
This change alone saves 86 bytes of RAM on AVR (e.g., Arduino UNO ) and 108 bytes on ESP8266. Again, this only saves memory for Harvard architectures, which uses different address spaces for program (Flash) and data (SRAM).
Float conversion tables moved to Flash
The second place where I moved data to program memory is in the float-to-string and string-to-float conversion code. This code contains three tables of constant floating-point values, which are good candidates for Flash memory.
This change is completely transparent to the user but saves a lot of RAM, especially if you use both serializeJson()
and deserializeJson()
.
On AVR, it saves 72 bytes; and on ESP8266, it saves between 80 and 224 bytes (depending on ARDUINOJSON_USE_DOUBLE
).
Again, von Neumann architectures (such as ESP32, megaAVR, and ARM) are unaffected by this change because they use the same address space for program and data.
A new error status: EmptyInput
In previous versions, IncompleteInput
could mean either “empty input” or “incomplete input”, causing some surprise among the users.
ArduinoJson 6.17 adds the error status EmptyInput
dedicated to the “empty input” case.
This change should have no impact on your code, unless you check specific error codes in a switch
statement, for example.
An easy way to detect memory pool overflows
With ArduinoJson 6, it’s always been easy to diagnose memory problems that occur during deserialization.
You just need to check the result of deserializeJson()
and deserializeMsgPack()
; the NoMemory
error indicates that memory pool is exhausted.
For serialization, however, detecting memory issues was really tricky.
You had to check the result of every call to JsonVariant::set()
and JsonVariant::add()
.
To help you detect memory issues, ArduinoJson 6.17 adds JsonDocument::overflowed()
which returns:
false
if the memory pool was sufficiently large, and theJsonDocument
contains all the values you insertedtrue
if the memory pool was too small, and some values are missing from theJsonDocument
Of course, this works for both serialization and deserialization.
Filtering for MessagePack
ArduinoJson 6.15 introduced input filtering for JSON but not for MessagePack.
In ArduinoJson 6.17, you can use DeserializationOption::Filter
with deserializeMsgPack()
the same way you do with deserializeJson()
.
Please see ArduinoJson 6.15: Filtering done right for details.
There is an unusual story for this feature: it was implemented twice.
In June 2020, Luca Passarella opened a feature request, and I kindly answered that I was not ready to develop it because too few users are interested in MessagePack.
In October 2020, he opened a Pull Request, but I had to decline it because it didn’t include any tests, and I don’t believe in tests written after the implementation.
Realizing how bad Luca needed this feature, I started working on my own implementation but using a test-driven approach.
At the same time, Luca added tests to his Pull Request and reach almost 100% coverage.
In the end, I included my version because I had more confidence in it, but I was sad for the wasted effort.
I hope Luca isn’t too disappointed that his implementation wasn’t retained.
Program size
You know I always keep an eye on the size of the library, so let’s see how ArduinoJson 6.17 compares to previous versions.
This graph shows the size of the sample programs when compiled for an Arduino UNO . As you can see, despite the new features, ArduinoJson 6.17 shrank a little.
Conclusion
This release results from a great effort (from Luca Passarella, and me), I hope you’ll appreciate it. I recommend that you upgrade as soon as possible, especially if you use an Arduino UNO because you can free up to 7.7% of RAM capacity.
Should you have any problem or question about this release, please open an issue on GitHub.
Lastly, remember that you can support the development of the project (and learn much interesting stuff) by purchasing my book Mastering ArduinoJson.