# A malloc-free JSON parser for Arduino The library is an thin C++ wrapper around the *jsmn* tokenizer: http://zserge.com/jsmn.html It's design to be very lightweight, works without any allocation on the heap (no malloc) and supports nested objects. It has been written with Arduino in mind, but it isn't linked to Arduino libraries so you can use this library on any other C++ project. ## Features * Based on the well-proven [jsmn](http://zserge.com/jsmn.html) tokenizer * Supports nested objects * Works with fixed memory allocation : no `malloc()` * Low footprint * MIT License ## Example char* json = "{\"Name\":\"Blanchon\",\"Skills\":[\"C\",\"C++\",\"C#\"],\"Age\":32,\"Online\":true}"; JsonParser<32> parser; JsonHashTable hashTable = parser.parseHashTable(json); if (!hashTable.success()) { return; } char* name = hashTable.getString("Name"); JsonArray skills = hashTable.getArray("Skills"); int age = hashTable.getLong("Age"); bool online = hashTable.getBool("Online"); ## How to use ? ### 1. Install the the library Download the library and extract it to: /libraries/ArduinoJonsParser ### 2. Import in your sketch Just add the following line on the to of your `.ino` file: #include ### 3. Create a parser To extract data from the JSON string, you need to create a `JsonParser`, and specify the number of token you allocate for the parser itself: JsonParser<32> parser; > #### How to choose the number of tokens ? > First you need to know exactly what a token is. A token is an element af the JSON object: either a key, a value, an hash-table or an array. > As an example the `char* json` on the top of this page contains 12 tokens (don't forget to count 1 for the whole object and 1 more for the array itself). > The more tokens you allocate, the more complex the JSON can be, but also the more memory will be occupied. > Each token takes 8 bytes, so `sizeof(JsonParser<32>)` is 256 bytes which is quite big in an Arduino with only 2KB of RAM. > Don't forget that you also have to store the JSON string in memory and it's probably big. > 32 tokens may seem small but it's very descent for an 8-bit processor, you wouldn't get better results with other JSON libraries. ### 4. Extract data To use this library, you need to know beforehand what is the type of data contained in the JSON string, which is extremely likely. #### Hash table Consider we have a `char* json` pointing to the following JSON string: { "Name":"Blanchon", "Skills":[ "C", "C++", "C#"], "Age":32, "Online":true } In this case the root object of the JSON string is a hash table, so you need to extract a `JsonHashTable`: JsonHashTable root = parser.parseHashTable(json); To check if the parsing was successful, you must check: if (!root.success()) { // Parsing fail: could be an invalid JSON, or too many tokens } And then extract the member you need: char* name = hashTable.getString("Name"); JsonArray skills = hashTable.getArray("Skills"); int age = hashTable.getLong("Age"); bool online = hashTable.getBool("Online"); #### Array Consider we have a `char* json` pointing to the following JSON string: [ [ 1.2, 3.4 ], [ 5.6, 7.8 ] ] In this case the root object of the JSON string is an array, so you need to extract a `JsonArray`: JsonArray root = parser.parseArray(json); To check if the parsing was successful, you must check: if (!root.success()) { // Parsing fail: could be an invalid JSON, or too many tokens } And then extract the content by its index in the array: JsonArray row0 = root.getArray(0); double a = row0.getDouble(0); or simply: double a = root.getArray(0).getDouble(0); ## Code size Theses tables has been created by analyzing the map file generated by AVR-GCC after adding `-Wl,-Map,foo.map` to the command line. As you'll see the code size if between 1680 and 3528 bytes, depending on the features you use. ### Minimum setup
Function Size in bytes
strcmp(char*,char*) 18
jsmn_init(jsmn_parser*) 20
jsmn_parse(jsmn_parser*, char const*, jsmntok_t*, unsigned int) 960
JsonParser::parse(char*) 106
JsonObjectBase::getNestedTokenCount(jsmntok_t*) 84
JsonObjectBase::getStringFromToken(jsmntok_t*) 68
JsonArray::JsonArray(char*, jsmntok_t*) 42
JsonArray::getToken(int) 112
JsonArray::getString(int) 18
JsonHashTable::JsonHashTable(char*, jsmntok_t*) 42
JsonHashTable::getToken(char*) 180
JsonHashTable::getString(char*) 18
TOTAL 1680
### Additional space to parse nested objects
Function Size in bytes
JsonArray::getArray(int) 42
JsonArray::getHashTable(int) 64
JsonHashTable::getArray(char*) 64
JsonHashTable::getHashTable(char*) 42
TOTAL 212
### Additional space to parse `bool` values
Function Size in bytes
JsonObjectBase::getBoolFromToken(jsmntok_t*) 82
JsonArray::getBool(int) 18
JsonHashTable::getBool(char*) 18
TOTAL 130
### Additional space to parse `double` values
Function Size in bytes
strtod(char*,int) 704
JsonObjectBase::getDoubleFromToken(jsmntok_t*) 44
JsonArray::getDouble(int) 18
JsonHashTable::getDouble(char*) 18
TOTAL 796
### Additional space to parse `long` values
Function Size in bytes
strtol(char*,char**,int) 606
JsonObjectBase::getLongFromToken(jsmntok_t*) 56
JsonArray::getLong(int) 18
JsonHashTable::getLong(char*) 18
TOTAL 710