Permalink
Browse files

finally it works with streaming

  • Loading branch information...
1 parent 8708473 commit 81e8839e13c2b817e1bddd1418764759ae30cfdc @interactive-matter committed Nov 3, 2010
Showing with 275 additions and 182 deletions.
  1. +80 −30 README
  2. +81 −112 aJSON.cpp
  3. +23 −6 utility/streamhelper.c
  4. +2 −1 utility/streamhelper.h
  5. +79 −26 utility/stringbuffer.c
  6. +10 −7 utility/stringbuffer.h
View
110 README
@@ -1,6 +1,6 @@
- aJson v0.1
+ aJson v1.0
- Copyright (c) 2001, Interactive Matter, Marcus Nowotny
+ Copyright (c) 2010, Interactive Matter, Marcus Nowotny
Based on the cJSON Library, Copyright (C) 2009 Dave Gamble
@@ -30,7 +30,7 @@ the cJSON implementation, reduced in size and removing one or two features:
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
+- There is an internal buffer eating up 256 bytes of ram
Most of the limitation will be gone in one of the future releases.
@@ -60,24 +60,26 @@ This is some JSON from this page: http://www.json.org/fatfree.html
}
}
+2. Parsing JSON
+
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
+Therefore 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);
+ Serial.println(name->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
+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
@@ -86,10 +88,6 @@ which can be either aJson_False, aJson_True, aJson_NULL, aJson_Number, aJson_Str
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);
@@ -98,8 +96,44 @@ 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.
+This deletes the objects and all values referenced by it.
+
+2.2 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 will not have to store the JSON string in memory.
+
+2.3 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.
+
+3. Creating JSON Objects from code
If you want to see how you'd build this struct in code?
@@ -113,7 +147,6 @@ If you want to see how you'd build this struct in code?
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.
@@ -123,34 +156,51 @@ 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.
-2. aJson Data Structures
+4. aJson Data Structures
aJson stores JSON objects in struct objects:
+// The aJson structure:
typedef struct aJsonObject {
- struct aJsonObject *next, *prev;
- struct aJsonObject *child;
+ 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;
+ char type; // The type of the item, as above.
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.
+ 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;
-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
@@ -184,7 +234,7 @@ and tokenise as you please.
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);
+ aJson.create<TYPE>Array(objects,24);
You simply pass a array of the respective type: char*[], int[] and so on.
Oops, something went wrong.

0 comments on commit 81e8839

Please sign in to comment.