[Arduino] JSON library 5.1
I recently released a new version of ArduinoJson, my JSON library for embedded platforms.
ArduinoJson is built around two concepts: fixed memory allocation and zero copy. I originally wrote this library two years ago to run on an Arduino Duemilanove with only 2KB of RAM. As far as I know, there is no other library that can do that properly.
- Support for
Yep. That’s it.
This is a very small improvement, but required a lot of effort in refactoring. I know very few people will be interested in this, but I needed it for a project and I knew it would force me to make the code more generic.
Up to now, I’ve been restraining myself from using template meta-programming techniques (TMP) in ArduinoJson because I wanted the code to be easy to understand, even for a novice in C++.
But that was mainly because, at that time, the documentation of ArduinoJson was very poor. Now it’s far for being complete, but it improved a lot. In particular, the API reference was missing and is now almost complete.
So why using TMP now? Simply because I allows me to remove a lot of duplication. Here is a simple example:
In ArduinoJson 5.0:
bool add(bool value); bool add(signed char value); bool add(signed long value); bool add(signed int value); bool add(signed short value); bool add(unsigned char value); bool add(unsigned long value); bool add(unsigned int value); bool add(unsigned short value); bool add(float value); bool add(double value); bool add(const char* value);
now becomes, in ArduinoJson 5.1:
template <typename T> bool add(T value, typename EnableIf<CanSet<T>::value>::type* = 0);
If it’s the first time that you’re in contact with TMP, this code snippet is probably hurting you badly. It uses a C++ rule called SFINAE, which says that the compiler will not issue an error if the template argument substitution fails. In this case
EnableIf<>::type will be
true, otherwise it will be undefined, leading to a substitution failure which is not an error. In the end, this declaration allows me to declare a template method that will be available only on certain types, those allowed by
So it should be clear now why I waited to have a comprehensive documentation before using TMP in ArduinoJson. Also you should see why I needed TMP to add yet another integral type: adding
long long and
unsigned long long would have forced me to add more overloads, but thanks to TMP, I just needed to change the result of the meta function
Don’t worry, this doesn’t affect the user code.
Configuration of the library
Of course, not everybody is going to use
long long in their program. First it’s a C++11 feature, and second it takes 64 bits which is not an option on 8-bit MCU.
So there are a bunch of preprocessor symbols that can be used to enable and disable features of the library. They are all defined in the
ArduinoJson/Configuration.hpp, but here is a summary:
ARDUINOJSON_USE_DOUBLEdetermines if the storage of floating point values is
double(the default in non-Arduino platforms) or
float(the default on Arduino platforms).
ARDUINOJSON_USE_LONG_LONGdetermines if the storage of integral values is
long long(the default in non-Arduino platforms) or
long(the default on Arduino platforms).
ARDUINOJSON_ENABLE_STD_STREAMallows to print
DynamicJsonBufferto return pointers aligned on CPU words (this is the default for most platforms).
As with previous versions, a crazy level of attention has been taken to keep the code small. I’m glad to announce that the example
JsonParserExample.ino lost 40 bytes! This is mostly due to a better inlining from the compiler, as I moved more code in the headers.
Here is an updated chart of the code size of ArduinoJson:
The orange line and blue lines are the size of the JSON generator and parser. See this previous article for details on this chart.
The next big change will be to make ArduinoJson a header only library. This will make the library easier to include in all projects (ie not just Arduino and CMake) and will stop the proliferation of the
ArduinoJson.h files in the source tree.
This is planned for version 6.0.
But before that, I need to fix issue #170: currently ArduinoJson stores all integral values into
long long, as we saw above), therefore when you set a
JsonVariant to an big
unsigned long value, it will be printed as a negative value.
This is planned for version 5.2 and will sadly make the code a little bigger.
- ArduinoJson on GitHub
- ArduinoJson documentation
- Announcement of v5.0, in September 2015
- Announcement of ArduinoJson 4.0, in November 2014
- Announcement of ArduinoJson 3.0, in July 2014
- Announcement of ArduinoJson 2.0, in July 2014
- Announcement of ArduinoJson 1.0, in January 2014
- Wikipedia: Substitution failure is not an error (SFINAE)
- “Metaprogramming in C++”, by Johannes Koskinen