aJson v0.1 Copyright (c) 2001, Interactive Matter, Marcus Nowotny Based on the cJSON Library, Copyright (C) 2009 Dave Gamble Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 1 Welcome to aJson. aJson is the attempt to port a complete JSON implementation to Arduino. It is based on the cJSON implementation, reduced in size and removing 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 - Name matching works case sensitive Most of the limitation will be gone in one of the future releases. JSON is described best here: http://www.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 aJson is a library to receive, understand, create or modify JSON strings directly in the Arduino. JSON is quite a standard, so that is perfect for exchanging data with other applications. I combination with HTTP it is suitable to implement REST Web Services. aJson provides functions to parse JSON strings to object models. Handle, search and create and modify JSON Object structures. This is some JSON from this page: http://www.json.org/fatfree.html { "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. Therefor the objects are translated into structs, with all the drawbacks it brings.s 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->value.valuestring); Note that the aJsonObject has a union 'value' which holds all possible value types as ovlerlays - 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 value.number.valueint or value.number.valuedouble, for aJson_String you can use value.valuestring, for True or False, you can use value.valuebool. If you want to change the name, you can do so by aJson.getObjectItem(jsonObject,"name")->valuestring="a new name"; 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. So take care for your string, you directly assigned. They are deleted too. 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 The whole library (nicely provided by cJSON) is optimized for easy usage. You can create and modify the object as easy as possible. 2. aJson Data Structures aJson stores JSON objects in struct objects: typedef struct aJsonObject { struct aJsonObject *next, *prev; struct aJsonObject *child; char type; union { char *valuestring; char valuebool; struct { int valueint; float valuefloat; } number; } value; char *name; // The item's name string, if this item is the child of, or is in the list of subitems of an object. } aJsonObject; PLEASE NOTE THAT ESPECIALLY THIS DATA STRUCTURE WILL BE SUBJECT TO MASSIVE CHANGES IN THE NEXT VERIONS - TO SAVE MORE MEMORY 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 value.number.valueint or value.number.valuedouble. If you're expecting an int, read valueint, if not read valuedouble. For aJson_String you can use value.valuestring, for True or False, you can use value.valuebool. next/prev is a doubly 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==0, but next potentially points on. The last sibling has next=0. 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. 3 Lists in aJson Lists are easily handled in aJson, to create a list you can simply use the provided API functions: aJson.create_array_of_anything(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. Have Fun!