updated README markdown, gitignore, added the Makefile and fixed weird comments in test.c

This commit is contained in:
Kevin Branigan 2011-08-22 00:47:25 -04:00
parent 4cc55858fd
commit ebba183f1e
4 changed files with 104 additions and 97 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
a.out
.svn
*.o

3
Makefile Normal file
View File

@ -0,0 +1,3 @@
all: cJSON.o
cc -Wall cJSON.c -c -o cJSON.o
cc -Wall cJSON.o test.c -lm

View File

@ -21,6 +21,7 @@
*/
Welcome to cJSON.
-----------------
cJSON aims to be the dumbest possible parser that you can get your job done with.
It's a single file of C, and a single header file.
@ -29,26 +30,25 @@ 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.
First up, how do I build?
Add cJSON.c to your project, and put cJSON.h somewhere in the header search path.
For example, to build the test app:
gcc cJSON.c test.c -o test -lm
./test
gcc cJSON.c test.c -o test -lm
./test
As a library, cJSON exists to take away as much legwork as it can, but not get in your way.
As a point of pragmatism (i.e. ignoring the truth), I'm going to say that you can use it
in one of two modes: Auto and Manual. Let's have a quick run-through.
I lifted some JSON from this page: http://www.json.org/fatfree.html
That page inspired me to write cJSON, which is a parser that tries to share the same
philosophy as JSON itself. Simple, dumb, out of the way.
Some JSON:
{
----------
{
"name": "Jack (\"Bee\") Nimble",
"format": {
"type": "rect",
@ -57,11 +57,12 @@ Some JSON:
"interlace": false,
"frame rate": 24
}
}
}
Assume that you got this from a file, a webserver, or magic JSON elves, whatever,
you have a char * to it. Everything is a cJSON struct.
Get it parsed:
cJSON *root = cJSON_Parse(my_json_string);
This is an object. We're in C. We don't have objects. But we do have structs.
@ -111,7 +112,9 @@ Sibling hs type False, name "interlace", and a sibling:
Sibling has type Number, name "frame rate", value 24
Here's the structure:
typedef struct cJSON {
---------------------
typedef struct cJSON {
struct cJSON *next,*prev;
struct cJSON *child;
@ -122,7 +125,7 @@ typedef struct cJSON {
double valuedouble;
char *string;
} cJSON;
} cJSON;
By default all values are 0 unless set by virtue of being meaningful.
@ -146,8 +149,8 @@ the root object, and traverse the structure (which is, formally, an N-tree),
and tokenise as you please. If you wanted to build a callback style parser, this is how
you'd do it (just an example, since these things are very specific):
void parse_and_callback(cJSON *item,const char *prefix)
{
void parse_and_callback(cJSON *item,const char *prefix)
{
while (item)
{
char *newprefix=malloc(strlen(prefix)+strlen(item->name)+2);
@ -157,14 +160,14 @@ void parse_and_callback(cJSON *item,const char *prefix)
item=item->next;
free(newprefix);
}
}
}
The prefix process will build you a separated list, to simplify your callback handling.
The 'dorecurse' flag would let the callback decide to handle sub-arrays on it's own, or
let you invoke it per-item. For the item above, your callback might look like this:
int callback(const char *name,int type,cJSON *item)
{
int callback(const char *name,int type,cJSON *item)
{
if (!strcmp(name,"name")) { /* populate name */ }
else if (!strcmp(name,"format/type") { /* handle "rect" */ }
else if (!strcmp(name,"format/width") { /* 800 */ }
@ -172,24 +175,24 @@ int callback(const char *name,int type,cJSON *item)
else if (!strcmp(name,"format/interlace") { /* false */ }
else if (!strcmp(name,"format/frame rate") { /* 24 */ }
return 1;
}
}
Alternatively, you might like to parse iteratively.
You'd use:
void parse_object(cJSON *item)
{
void parse_object(cJSON *item)
{
int i; for (i=0;i<cJSON_GetArraySize(item);i++)
{
cJSON *subitem=cJSON_GetArrayItem(item,i);
// handle subitem.
}
}
}
Or, for PROPER manual mode:
void parse_object(cJSON *item)
{
void parse_object(cJSON *item)
{
cJSON *subitem=item->child;
while (subitem)
{
@ -198,7 +201,7 @@ void parse_object(cJSON *item)
subitem=subitem->next;
}
}
}
Of course, this should look familiar, since this is just a stripped-down version
of the callback-parser.
@ -212,10 +215,10 @@ You can, of course, hand your sub-objects to other functions to populate.
Also, if you find a use for it, you can manually build the objects.
For instance, suppose you wanted to build an array of objects?
cJSON *objects[24];
cJSON *objects[24];
cJSON *Create_array_of_anything(cJSON **items,int num)
{
cJSON *Create_array_of_anything(cJSON **items,int num)
{
int i;cJSON *prev, *root=cJSON_CreateArray();
for (i=0;i<24;i++)
{
@ -224,7 +227,7 @@ cJSON *Create_array_of_anything(cJSON **items,int num)
prev=objects[i];
}
return root;
}
}
and simply: Create_array_of_anything(objects,24);
@ -235,7 +238,6 @@ of those objects.
As soon as you call cJSON_Print, it renders the structure to text.
The test.c code shows how to handle a bunch of typical cases. If you uncomment
the code, it'll load, parse and print a bunch of test files, also from json.org,
which are more complex than I'd care to try and stash into a const char array[].
@ -243,5 +245,4 @@ which are more complex than I'd care to try and stash into a const char array[].
Enjoy cJSON!
- Dave Gamble, Aug 2009

4
test.c
View File

@ -69,7 +69,7 @@ void create_objects()
cJSON_AddFalseToObject (fmt,"interlace");
cJSON_AddNumberToObject(fmt,"frame rate", 24);
out=cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); free(out); /* Print to text, Delete the cJSON, print it, release the string.
out=cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); free(out); /* Print to text, Delete the cJSON, print it, release the string. */
/* Our "days of the week" array: */
const char *strings[7]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
@ -142,7 +142,7 @@ int main (int argc, const char * argv[]) {
doit(text4);
doit(text5);
/* Parse standard testfiles:
/* Parse standard testfiles: */
/* dofile("../../tests/test1"); */
/* dofile("../../tests/test2"); */
/* dofile("../../tests/test3"); */