Arduino JSON Library

JSON structure

What is JSON

Exchanging data with other computers can be a daunting task with Arduino. No matter if you just want to pass some information to Processing, to a Web Service or something else – You always have to encode the data and decode the answer.

There always have been solutions like XML for structured data. But XML is hard to decode, complicated an takes up a lot of space. And then there is JSON.
JSON is described best on json.org:

It’s like XML, but fat-free. You use it to move data around, store things, or just generally represent your program’s state.
JSON is especially useful to exchange data efficiently with e.g. JavaScript, Java, C++, Processing or anything else.

JSON is quite widespread used so that is perfect for exchanging data with other applications. In combination with HTTP it is suitable to implement REST Web Services.

What is aJson

aJson is an Arduino library to enable JSON processing with Arduino. It easily enables you to decode, create, manipulate and encode JSON directly from and to data structures. By this you don’t have to bother with data encoding and decoding – this will aJson handle for you. aJson is a library to receive, understand, create or modify JSON strings directly in the Arduino. aJson provides functions to parse JSON strings to object models. Handle, search and create and modify JSON Object structures.

It is based on the cJSON implementation, reduced in size and mising one or two features:

  • The code has very limited support on ATmega168 – there is just not enough memory and memory fragmentation is a serious problem
  • Arrays and Lists are max 255 elements big
  • There is no proper Unicode handling in this code
  • There is an internal buffer eating up 256 bytes of RAM

You can download the latest version of aJsons from Github. If you notice any problem just file an issue so that I can deal with it.

Parsing JSON

This is some JSON from this page:

{
"name": "Jack (\"Bee\") Nimble",
"format": {
"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,
"frame rate": 24
}
}

To parse such a structure with aJson you simply convert it to a object tree:

aJsonObject* jsonObject = aJson.parse(json_string);

Assuming you got the JSON string in the variable json_string – as a char*. This is an object. We’re in C. We don’t have objects. But we do have structs. Therefore the objects are translated into structs, with all the drawbacks it brings. Now we can e.g. retrieve the value for name:

aJsonObject* name = aJson.getObjectItem(root, "name");

The value of name can be retrieved via:

Serial.println(name->valuestring);

Note that the aJsonObject has a union which holds all possible value types as overlays – you can get only useful data for the type which you have at hand. You can get the type as
name->type
which can be either aJson_False, aJson_True, aJson_NULL, aJson_Number, aJson_String, aJson_Array or aJson_Object. For aJson_Number you can use valueint for Integers or valuedouble for floating point numbers. For aJson_String you can use valuestring. For True or False, you can use valuebool.

To render the object back to a string you can simply call
char *json_String=aJson.print(jsonObject);
Finished? Delete the root (this takes care of everything else).
aJson.delete(root);
This deletes the objects and all values referenced by it.

Parsing streams

As you can see this will eat up lots of memory. Storing the original string and the JSON object is a bit too much for your Arduino – it will most likely use up all the memory. Therefore it is better to parse streams instead of strings.
A stream in C is a FILE* – on Arduino there are some special streams, but later adapters will be provided. So if you for example read from a FILE* stream you can simply call
aJsonObject* jsonObject = aJson.parse(file);
By that you don’t have to store the JSON string in memory.

You can of course print JSON objects directly to a FILE* stream:
aJson.print(jsonObject,stream);

Filtering while parsing

Any JSON respond can have object name/value pairs your code either does not understand or is not interested in. To avoid those values to go into your memory you can simply add filters to your parsing request. A set of filter is just a list of names you are interested in, ended by a null value. If you are only interested in “name”, “format”, “height” and “width” in the above example you can do it like:
char** jsonFilter = {"name,"format","height","width",NULL};
aJsonObject* jsonObject = aJson.parse(json_string,json_filter);
(assuming you got the JSON string in the variable json_string – as a char*)

By that only the following structure is parsed – the rest will be ignored:
{
"name": "Jack (\"Bee\") Nimble",
"format": {
"width": 1920,
"height": 1080,
}
}

It is good practice to always use the filtering feature to parse JSON answers, to avoid unknown objects swamping your memory.

Creating JSON Objects from code

If you want to see how you’d build this struct in code?

aJsonObject *root,*fmt;
root=aJson.createObject();
aJson.addItemToObject(root, "name", aJson.createString("Jack (\"Bee\") Nimble"));
aJson.addItemToObject(root, "format", fmt = aJson.createObject());
aJson.addStringToObject(fmt,"type", "rect");
aJson.addNumberToObject(fmt,"width", 1920);
aJson.addNumberToObject(fmt,"height", 1080);
aJson.addFalseToObject (fmt,"interlace");
aJson.addNumberToObject(fmt,"frame rate", 24);

The root object has: Object Type and a Child
The Child has name “name”, with value “Jack (“Bee”) Nimble”, and a sibling:
Sibling has type Object, name “format”, and a child.
That child has type String, name “type”, value “rect”, and a sibling:
Sibling has type Number, name “width”, value 1920, and a sibling:
Sibling has type Number, name “height”, value 1080, and a sibling:
Sibling hs type False, name “interlace”, and a sibling:
Sibling has type Number, name “frame rate”, value 24

If you want to create an array it works nearly the same way:

aJsonObject* root = aJson.createArray();
aJsonObject* day;
day=aJson.createItem("Monday");
aJson.addItemToArray(root, day);
day=aJson.createItem("Tuesday");
aJson.addItemToArray(root, day);
day=aJson.createItem("Wednesday");
aJson.addItemToArray(root, day);
day=aJson.createItem("Thursday");
aJson.addItemToArray(root, day);
day=aJson.createItem("Friday");
aJson.addItemToArray(root, day);
day=aJson.createItem("Saturday");
aJson.addItemToArray(root, day);
day=aJson.createItem("Sunday");
aJson.addItemToArray(root, day);

The whole library (nicely provided by cJSON) is optimized for easy usage. You can create and modify the object as easy as possible.

aJson Data Structures

aJson stores JSON objects in struct objects:

// The aJson structure:
typedef struct aJsonObject {
char *name; // The item's name string, if this item is the child of, or is in the list of subitems of an object.
struct aJsonObject *next, *prev; // next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem
struct aJsonObject *child; // An array or object item will have a child pointer pointing to a chain of the items in the array/object.
char type; // The type of the item, as above.
union {
char *valuestring; // The item's string, if type==aJson_String
char valuebool; //the items value for true & false
int valueint; // The item's number, if type==aJson_Number
float valuefloat; // The item's number, if type==aJson_Number
};
} aJsonObject;

By default all values are 0 unless set by virtue of being meaningful.

Note that the aJsonObject has a union ‘value’ which holds all possible value types as overlays – you can get only useful data for the type which you have at hand. You can get the type as

name->type

which can be either aJson_False, aJson_True, aJson_NULL, aJson_Number, aJson_String, aJson_Array or aJson_Object. For aJson_Number you can use valueint or valuedouble. If you’re expecting an int, read valueint, if not read valuedouble. For aJson_String you can use valuestring, for True or False, you can use valuebool.

The pointers next/prev are a double linked list of siblings. next takes you to your sibling, prev takes you back from your sibling to you.
Only objects and arrays have a “child“, and it’s the head of the doubly linked list. A “child” entry will have prev==NULL, but next potentially points on. The last sibling has next=NULL. The type expresses Null/True/False/Number/String/Array/Object, all of which are defined in aJson.h

Any entry which is in the linked list which is the child of an object will have a “string” which is the “name” of the entry. When I said “name” in the above example, that’s “string”. “string” is the JSON name for the ‘variable name’ if you will.

Now you can trivially walk the lists, recursively, and parse as you please. You can invoke aJson.parse to get aJson to parse for you, and then you can take the root object, and traverse the structure (which is, formally, an N-tree), and tokenise as you please.

Lists in aJson

Lists are easily handled in aJson, to create a list you can simply use the provided API functions:

aJson.createArray(objects,24);

You simply pass a array of the respective type: char*[], int[] and so on.

aJSON doesn’t make any assumptions about what order you create things in. You can attach the objects, as above, and later add children to each of those objects with

aJson.addItemToArray()

or remove them with aJson.deleteItemFromArray() – which also deletes the objects, or aJson.detachItemFromArray() - which does not free the memory

As soon as you call aJson.print(), it renders the structure to text.

{ 21 comments… read them below or add one }

Amorim February 17, 2011 at 17:36

hello,

I’m not getting success to compile the “test.pde” I’m
getting the following error: error: ‘struct aJsonObject’
has no member named ‘value’, could you help me?

Thanks!

Reply

Marcus February 17, 2011 at 18:09

Yes,
In the current version there are some Bugs in the example sketch. Will look at it tomorrow.

Reply

Marcus February 18, 2011 at 10:12

I have just released version 1.3 of aJson which fixes the problem. Geit it from the aJson download page.

Reply

Pascal Delprat February 19, 2011 at 23:04

Hello,
Thanks for this excellent library. I just have some issues with printFloat :

- truncated value due to “%u.” instead of “%lu.” at line 196
- print a “.” even if FLOAT_PRECISION = 0
- print “xxx.00999″ even if I use a unsigned long as a vlaue

After reading printFloat in Print.cpp, here is my proposition :

int
aJsonClass::printFloat(aJsonObject *item, FILE* stream)
{
uint8_t digits = FLOAT_PRECISION;
if (item != NULL)
{
double d = item->valuefloat;
if (d<0.0) {
fprintf_P(stream,PSTR(“-”));
d=-d;
}

// Round correctly so that print(1.999, 2) prints as “2.00″
double rounding = 0.5;
for (uint8_t i=0; i 0)
fprintf_P(stream,PSTR(“.”));

// Extract digits from the remainder one at a time
while (digits– > 0)
{
remainder *= 10.0;
int toPrint = int(remainder);
fprintf_P(stream,PSTR(“%u”), toPrint);
remainder -= toPrint;
}

}
//printing nothing is ok
return 0;
}

Best regards,
Pascal

Reply

Marcus February 20, 2011 at 08:49

Thanks,

Will be integrated as soon as possible to the HEAD version.
Sorry float printing and parsing is still a bit damaged. Hope to get it fixed soon.

So much to do & so little time …

Reply

Lutz August 25, 2011 at 11:01

Hi,

1. there seems to be a memory leak in the “print” method.
2. there is a peculiar way to handle .999 as .899.

[… here goes some debug code and test output, remove by the editor]

Reply

Marcus August 25, 2011 at 14:38

Sorry, the comments are not for reporting issues. For issues please visit the issue page on github – makes it much easier for both of us.
Thanks

Marcus

Reply

Chris August 25, 2011 at 22:39

Confused. In arduino how do I open a file stream of type FILE*? There are a couple kinds of streams in sdfatlib, but none like the c style FILE* stream = fopen(“stream.txt”,”r”); I am trying to store the json on the sd card and recall it later without murdering the memory. Any thoughts?

Reply

Marcus August 25, 2011 at 23:01

Hi Chris,
the FILE* streams are just a little trick to handle with streams. I think real Streams were introduce in Arduino later (or at the same) time. You can check the implementations in https://github.com/interactive-matter/aJson/blob/master/utility/streamhelper.c
In the stream helper I create streams from strings. This was then integrated into the main aJson class to also accept strings instead of FILE* streams.
So what is missing is the corresponding methods in the stream helper to open and close FILE* streams (and by that creating and closing the streams).
If you like clone the project in github (so that I can see and integrate your changes) and change the code.

Marcus

Reply

Chris August 25, 2011 at 23:35

Thanks for pointing me in the right direction. I’ll have a look! So if I (or anyone else reading along) edit it, it will have to accept the sdfatlib stream of fstream. Sdfatlib is here: http://code.google.com/p/sdfatlib/ I’ll see if I can do anything.

Dunkel December 22, 2011 at 06:43

How do you use a SdFile or a File (from SD.h) to send the stream to the aJSON, do i need to read the whole file? and parse it as a string and not as a file?

Kristian November 10, 2011 at 09:58

I am getting a error when I try to delete an aJson Object:

Line of code:
aJson.delete(jsonObject);

Error:
sketch_nov08a.cpp: In function ‘void handle()’:
sketch_nov08a:183: error: expected unqualified-id before ‘delete’
sketch_nov08a:183: error: expected `;’ before ‘delete’

Thanks!

Reply

Tim January 25, 2012 at 03:29

Trying to parse a json string using the aJSON library. The json string consists of an array of objects, not just a single object. For example a 2-object array looks like:

[{"id":"1","name":"Garage","addressH":0,"addressL":2,"offset":-312,"scale":0.388,"interval":50000},{"id":"2","name":"House","addressH":0,"addressL":3,"offset":-312,"scale":0.388,"interval":50000}]

I was hoping the following would work to get an array of aJsonObjects, but it yells at me:

aJsonObject* sensorConfig[] = aJson.parse(buff);

generates “error: initializer fails to determine size of ‘sensorConfig’”

Any help appreciated.

Reply

Marcus January 29, 2012 at 21:50

I think you should not create an array of objects. The Json Array is an object by itself. Leaving out the [] should help.

Reply

Nicolas March 1, 2012 at 21:58

Hi,

I am testing aJson.
I try to create a field with a null number and print the result. I get this result : {“test”:0} instead of {“test”: NULL}

If I try to set the value of the field, I get this result :
{“test”:0} instead of {“test”: 26.0}

And this is the code :
#include

void setup() {
Serial.begin(9600);
}

void loop(){
aJsonObject *root;
root=aJson.createObject();
aJson.addNumberToObject(root, “test”, NULL);
Serial.println(aJson.print(root));
aJsonObject* name = aJson.getObjectItem(root, “test”);
name->valuefloat = 26.0;
Serial.println(aJson.print(root));
Serial.println();
delay(1000);
}

Thanks for your help.

Reply

kimyoung August 2, 2012 at 03:36

I am testing aJson.
this is my arduino sketch code

void testObjects() {
aJsonObject* root = aJson.createObject();
aJson.addItemToObject(root, “Version”, aJson.createItem(1.0));
aJsonObject* fmt = aJson.createObject();
aJson.addItemToObject(root, “format”, fmt);
aJson.addStringToObject(fmt, “SensorName”, “TMP36″);
aJson.addNumberToObject(fmt, “-Temperature”, temperature);
freeMem(“with object”);

char* string = aJson.print(root);
if (string != NULL) {
Serial.println(string);

}

aJson.deleteItem(root);
free(string);
freeMem(“after deletion”);
delay(4000);
}

void loop() {
testObjects();
}

void loop()
{
if(Serial.available() > 0)
{
memset(Jsondata, 0×00, Length);
Serial.readBytes(Jsondata,Length);

aJsonObject* root = aJson.createObject();
root = aJson.parse(Jsondata);
aJsonObject *test = aJson.getObjectItem(root, “format”);
aJsonObject *tmp = aJson.getObjectItem(test, “SensorName”);

char *string = tmp->valuestring;
if(string != NULL)
{
Serial.println(string);

}
else
{
return;
}

aJson.deleteItem(root);

}
}

In this case, Data Take `s result is well done

but sometimes null code or trash code exist.
I want to perfect Take code.
Thanks for your help

Reply

Andre Bertier December 4, 2012 at 20:39

Helo,

I am receiving the following string:

{\”Group\”:1}

When a tell Json to get the value of “Group” by doing
aJsonObject* group = aJson.getObjectItem(jsonObject, “Group”);

Nothing happens.

However if I get rid of the backslashes like this

{ “Group” : 1}, then it works.

The problem is that the string I receive is created by a Json on C# but it seems aJson can’t understand the backslashes as escape chars for quotes.

What should I do? Please, help me!

Reply

AceoStar March 25, 2013 at 01:50

Could we get an example sketch of how to “process” posted data from the arduino? I have a LED control system. I want to be able to post JSON to the device from another device and act on the posted data.

Reply

donsan March 10, 2014 at 05:12

Hello!
I am so interested in the json with arduino, but i puzzle what the hardwear need?
Thanks!!

Reply

Marcus April 2, 2014 at 16:17

uhm – an Arduino

Reply

Marcus December 22, 2011 at 06:46

You can easily adapt the streaming interface of AJson to the Arduino Stream.
But to be honest this is something on my to do list already.

Reply

Leave a Comment

{ 4 trackbacks }