Arduino JSON library - Generator ================================ *An elegant and efficient JSON encoder for embedded systems.* It's design to have the most intuitive API, the smallest footprint and works without any allocation on the heap (no malloc). It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library in any other C++ project. Features -------- * Elegant API, very easy to use * Fixed memory allocation (no malloc) * Small footprint * Supports nested objects * Implements Arduino's `Printable interface * MIT License Example ------- JsonArray<2> array; array.add<6>(48.756080); // <6> specifies the number of digits in the output array.add<6>(2.302038); // (the default is 2) JsonObject<3> root; root["sensor"] = "gps"; root["time"] = 1351824120; root["data"] = array; Serial.print(root); // {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]} How to use? ------------ ### 1. Install the library Download the library and extract it to: /libraries/ArduinoJson ### 2. Import in your sketch Just add the following lines at the top of your `.ino` file: #include using namespace ArduinoJson::Generator; > ##### Having a namespace conflict? > To be able to use both `ArduinoJson::Generator` and `ArduinoJson::Parser` in the same file, you need to do one of the followings: > > * Put the `using` statements into different functions > * `using namespace ArduinoJson`, then prefix the type names by `Generator::` or `Parser::` > * Create aliases for the namespaces or the types (C++11 only) ### 3. Create object tree In order to generate a JSON string, you need to build the equivalent object tree. You usually start by the root which can be either a JSON Array or a JSON Object. #### JSON Array You create an array with the following line: JsonArray<8> array; See the little `<8>`? It's a template parameter that gives the capacity of the array, it's the maximum number of elements you can put in it. > ##### About the capacity > As stated in the feature list, this library works with a fixed memory allocation. > This means that the size of the object must be know at the compilation time, therefore you can **not** use a variable to set the capacity of the array. Then you can add strings, integer, booleans, etc: array.add("bazinga!"); array.add(42); array.add(true); There are two syntaxes for floating point values: array.add<4>(3.1415); // 4 digits: "3.1415" array.add(3.14); // 2 digits: "3.14" > ##### About floating point precision > The overload of `add()` with 2 parameters allows you to specify the number of decimals to save in the JSON string. > When you use the overload with one parameter, you use the default number of decimals which is two. > Note that this behavior is the exact same as Arduino's `Print::print(double,int);` which is implemented by `Serial`. > So you may already be familiar with it. Finally you can add nested object to the array: JsonArray<8> nestedArray; array.add(nestedArray); or JsonObject<8> nestedObject; array.add(nestedObject); > ##### CAUTION! Nested objects must be in memory > Calling `add()` makes the `JsonArray` store a pointer to the nested object. > This is designed to avoid memory duplication. > But it can only work if the object is in memory when `printTo()` is executed. > For instance, don't do this: > > void addNestedObject() > { > JsonObject<2> nestedObject; > // ... > array.add(nestedObject); // <- DON'T !! > > // array now contains a pointer to a local variable that will be > // discarded as soon as the function exits > } > > For the same reason, don't do this either: > > for( int i=0; i<100; i++) > { > JsonObject<2> nestedObject; > // ... > array.add(nestedObject); // <- DON'T !! > } > // array now contains 100 pointers to the same a local variable > // that is out of the scope anyway #### JSON Object You create a JSON object (ie hash-table/dictionary) with the following line: JsonObject<8> object; Like with the array class, there is a template parameter that gives the capacity of the object. Then you can add strings, integer, booleans, etc: object["key1"] = "bazinga!"; object["key2"] = 42; object["key3"] = true; As for the arrays, there are two syntaxes for the floating point values: object["key4"].set<4>(3.1415); // 4 digits "3.1415" object["key5"] = 3.1415; // default: 2 digits "3.14" Finally you can add nested objects: JsonArray<8> nestedArray; object["key6"] = nestedArray; or JsonObject<8> nestedObject; object["key7"] = nestedObject; > ##### Other JsonObject functions > * `object.add(key, value)` is a synonym for `object[key] = value` > * `object.containsKey(key)` returns `true` is the `key` is present in `object` > * `object.remove(key)` removes the `value` associated with `key` ### 4. Get the JSON string There are two ways tho get the resulting JSON string. Depending on your project, you may need to dump the string in a classic `char[]` or send it to a stream like `Serial` or `EthernetClient `. Both ways are the easy way :-) #### Use a classic `char[]` Whether you have a `JsonArray` or a `JsonObject`, simply call `printTo()` with the destination buffer, like so: char buffer[256]; array.printTo(buffer, sizeof(buffer)); #### Send to a stream It's very likely that the generated JSON will end up in a stream like `Serial` or `EthernetClient `, so you can save some time and memory by doing this: Serial.print(array); or array.printTo(Serial); > ##### About the Printable interface > `JsonArray` and `JsonObject` implement Arduino's `Printable` interface. > This is why you can call `Serial.print()` like in the example above. > You can do the same with any other implementation of `Print`: `HardwareSerial`, `SoftwareSerial`, `LiquidCrystal`, `EthernetClient`, `WiFiClient`... Memory usage ------------ Here are the size of the main classes of the library. This table is for an 8-bit Arduino, types would be bigger on a 32-bit processor. | Type | Size in bytes | | --------------------| ------------- | | JsonArray<N> | 8 + 6 x N | | JsonObject<N> | 8 + 8 x N | Code size --------- The following values has been obtained with Arduino IDE 1.0.5, targeting an Arduino Duelmilanove with an ATmega 328. ### Minimum setup | Function | Size | | ----------------------------------- | ---- | | `JsonObjectBase::printTo()` | 234 | | `EscapedString::printTo()` | 196 | | `JsonArrayBase::printTo()` | 164 | | `Print::print(char const*)` | 146 | | `JsonObjectBase::operator[]` | 114 | | `JsonObjectBase::getMatchingPair()` | 72 | | `JsonValue::printPrintableTo()` | 40 | | `JsonValue::printStringTo()` | 12 | ### Additional space for integers | Function | Size | | ---------------------------- | ---- | | `Print::print(long, int)` | 328 | | `JsonValue::printLongTo()` | 22 | ### Additional space for floating point | Function | Size | | ------------------------------ | ---- | | `Print::print(double, int)` | 1548 | | `JsonValue::printDouleTo<2>()` | 22 |