mirror of
https://github.com/DaveGamble/cJSON.git
synced 2023-08-10 21:13:26 +03:00
README: More formatting
This commit is contained in:
parent
df1ffa1e0b
commit
a22da43578
209
README.md
209
README.md
@ -94,7 +94,7 @@ make
|
|||||||
make DESTDIR=$pkgdir install
|
make DESTDIR=$pkgdir install
|
||||||
```
|
```
|
||||||
|
|
||||||
CMake supports a lot of different platforms, not only UNIX Makefiles, but only UNIX Makefiles have been tested. It works on GNU/Linux and has been confirmed to compile on some versions of macOS, FreeBSD, Cygwin, Solaris and OpenIndiana.
|
CMake supports a lot of different platforms, not only UNIX Makefiles, but only UNIX Makefiles have been tested. It works on GNU/Linux and has been confirmed to compile on some versions of macOS, Cygwin, Solaris and OpenIndiana.
|
||||||
|
|
||||||
#### Makefile
|
#### Makefile
|
||||||
If you don't have CMake available, but still have make. You can use the makefile to build cJSON:
|
If you don't have CMake available, but still have make. You can use the makefile to build cJSON:
|
||||||
@ -123,7 +123,7 @@ If you want, you can install the compiled library to your system using `make ins
|
|||||||
```
|
```
|
||||||
|
|
||||||
Assume that you got this from a file, a webserver, or magic JSON elves, whatever,
|
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.
|
you have a `char *` to it. Everything is a `cJSON` struct.
|
||||||
Get it parsed:
|
Get it parsed:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
@ -134,20 +134,20 @@ This is an object. We're in C. We don't have objects. But we do have structs.
|
|||||||
What's the framerate?
|
What's the framerate?
|
||||||
|
|
||||||
```c
|
```c
|
||||||
cJSON * format = cJSON_GetObjectItem(root,"format");
|
cJSON *format = cJSON_GetObjectItem(root, "format");
|
||||||
int framerate = cJSON_GetObjectItem(format,"frame rate")->valueint;
|
int framerate = cJSON_GetObjectItem(format, "frame rate")->valueint;
|
||||||
```
|
```
|
||||||
|
|
||||||
Want to change the framerate?
|
Want to change the framerate?
|
||||||
|
|
||||||
```c
|
```c
|
||||||
cJSON_GetObjectItem(format,"frame rate")->valueint = 25;
|
cJSON_GetObjectItem(format, "frame rate")->valueint = 25;
|
||||||
```
|
```
|
||||||
|
|
||||||
Back to disk?
|
Back to disk?
|
||||||
|
|
||||||
```c
|
```c
|
||||||
char * rendered = cJSON_Print(root);
|
char *rendered = cJSON_Print(root);
|
||||||
```
|
```
|
||||||
|
|
||||||
Finished? Delete the root (this takes care of everything else).
|
Finished? Delete the root (this takes care of everything else).
|
||||||
@ -160,7 +160,8 @@ That's AUTO mode. If you're going to use Auto mode, you really ought to check po
|
|||||||
before you dereference them. If you want to see how you'd build this struct in code?
|
before you dereference them. If you want to see how you'd build this struct in code?
|
||||||
|
|
||||||
```c
|
```c
|
||||||
cJSON *root,*fmt;
|
cJSON *root;
|
||||||
|
cJSON *fmt;
|
||||||
root = cJSON_CreateObject();
|
root = cJSON_CreateObject();
|
||||||
cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
|
cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
|
||||||
cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject());
|
cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject());
|
||||||
@ -172,92 +173,113 @@ cJSON_AddNumberToObject(fmt, "frame rate", 24);
|
|||||||
```
|
```
|
||||||
|
|
||||||
Hopefully we can agree that's not a lot of code? There's no overhead, no unnecessary setup.
|
Hopefully we can agree that's not a lot of code? There's no overhead, no unnecessary setup.
|
||||||
Look at test.c for a bunch of nice examples, mostly all ripped off the json.org site, and
|
Look at `test.c` for a bunch of nice examples, mostly all ripped off the [json.org](http://json.org) site, and
|
||||||
a few from elsewhere.
|
a few from elsewhere.
|
||||||
|
|
||||||
What about manual mode? First up you need some detail.
|
What about manual mode? First up you need some detail.
|
||||||
Let's cover how the cJSON objects represent the JSON data.
|
Let's cover how the `cJSON` objects represent the JSON data.
|
||||||
cJSON doesn't distinguish arrays from objects in handling; just type.
|
cJSON doesn't distinguish arrays from objects in handling; just type.
|
||||||
Each cJSON has, potentially, a child, siblings, value, a name.
|
Each `cJSON` has, potentially, a child, siblings, value, a name.
|
||||||
|
|
||||||
The root object has: Object Type and a Child
|
* The `root` object has: *Object* Type and a Child
|
||||||
The Child has name "name", with value "Jack ("Bee") Nimble", and a sibling:
|
* The Child has name "name", with value "Jack ("Bee") Nimble", and a sibling:
|
||||||
Sibling has type Object, name "format", and a child.
|
* Sibling has type *Object*, name "format", and a child.
|
||||||
That child has type String, name "type", value "rect", and a sibling:
|
* 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 "width", value 1920, and a sibling:
|
||||||
Sibling has type Number, name "height", value 1080, and a sibling:
|
* Sibling has type *Number*, name "height", value 1080, and a sibling:
|
||||||
Sibling has type False, name "interlace", and a sibling:
|
* Sibling has type *False*, name "interlace", and a sibling:
|
||||||
Sibling has type Number, name "frame rate", value 24
|
* Sibling has type *Number*, name "frame rate", value 24
|
||||||
|
|
||||||
# Here's the structure:
|
### Here's the structure:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
typedef struct cJSON {
|
typedef struct cJSON {
|
||||||
struct cJSON *next,*prev;
|
struct cJSON *next,*prev;
|
||||||
struct cJSON *child;
|
struct cJSON *child;
|
||||||
|
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
char *valuestring;
|
char *valuestring;
|
||||||
int valueint;
|
int valueint;
|
||||||
double valuedouble;
|
double valuedouble;
|
||||||
|
|
||||||
char *string;
|
char *string;
|
||||||
} cJSON;
|
} cJSON;
|
||||||
```
|
```
|
||||||
|
|
||||||
By default all values are 0 unless set by virtue of being meaningful.
|
By default all values are 0 unless set by virtue of being meaningful.
|
||||||
|
|
||||||
next/prev is a doubly linked list of siblings. next takes you to your sibling,
|
`next`/`prev` is a doubly linked list of siblings. `next` takes you to your sibling,
|
||||||
prev takes you back from your sibling to you.
|
`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.
|
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.
|
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
|
The type expresses *Null*/*True*/*False*/*Number*/*String*/*Array*/*Object*, all of which are `#defined` in
|
||||||
cJSON.h
|
`cJSON.h`.
|
||||||
|
|
||||||
A Number has valueint and valuedouble. If you're expecting an int, read valueint, if not read
|
A *Number* has `valueint` and `valuedouble`. If you're expecting an `int`, read `valueint`, if not read
|
||||||
valuedouble.
|
`valuedouble`.
|
||||||
|
|
||||||
Any entry which is in the linked list which is the child of an object will have a "string"
|
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".
|
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.
|
`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.
|
Now you can trivially walk the lists, recursively, and parse as you please.
|
||||||
You can invoke cJSON_Parse to get cJSON to parse for you, and then you can take
|
You can invoke `cJSON_Parse` to get cJSON to parse for you, and then you can take
|
||||||
the root object, and traverse the structure (which is, formally, an N-tree),
|
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
|
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):
|
you'd do it (just an example, since these things are very specific):
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void parse_and_callback(cJSON *item,const char *prefix)
|
void parse_and_callback(cJSON *item, const char *prefix)
|
||||||
{
|
{
|
||||||
while (item)
|
while (item)
|
||||||
{
|
{
|
||||||
char *newprefix = malloc(strlen(prefix) + strlen(item->name) + 2);
|
char *newprefix = malloc(strlen(prefix) + strlen(item->name) + 2);
|
||||||
sprintf(newprefix,"%s/%s",prefix,item->name);
|
sprintf(newprefix, "%s/%s", prefix, item->name);
|
||||||
int dorecurse = callback(newprefix, item->type, item);
|
int dorecurse = callback(newprefix, item->type, item);
|
||||||
if (item->child && dorecurse) parse_and_callback(item->child, newprefix);
|
if (item->child && dorecurse)
|
||||||
item = item->next;
|
{
|
||||||
free(newprefix);
|
parse_and_callback(item->child, newprefix);
|
||||||
}
|
}
|
||||||
|
item = item->next;
|
||||||
|
free(newprefix);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The prefix process will build you a separated list, to simplify your callback handling.
|
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
|
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:
|
let you invoke it per-item. For the item above, your callback might look like this:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
int callback(const char *name,int type,cJSON *item)
|
int callback(const char *name, int type, cJSON *item)
|
||||||
|
{
|
||||||
|
if (!strcmp(name, "name"))
|
||||||
{
|
{
|
||||||
if (!strcmp(name,"name")) { /* populate name */ }
|
/* populate name */
|
||||||
else if (!strcmp(name,"format/type") { /* handle "rect" */ }
|
|
||||||
else if (!strcmp(name,"format/width") { /* 800 */ }
|
|
||||||
else if (!strcmp(name,"format/height") { /* 600 */ }
|
|
||||||
else if (!strcmp(name,"format/interlace") { /* false */ }
|
|
||||||
else if (!strcmp(name,"format/frame rate") { /* 24 */ }
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(name, "format/type")
|
||||||
|
{
|
||||||
|
/* handle "rect" */ }
|
||||||
|
else if (!strcmp(name, "format/width")
|
||||||
|
{
|
||||||
|
/* 800 */
|
||||||
|
}
|
||||||
|
else if (!strcmp(name, "format/height")
|
||||||
|
{
|
||||||
|
/* 600 */
|
||||||
|
}
|
||||||
|
else if (!strcmp(name, "format/interlace")
|
||||||
|
{
|
||||||
|
/* false */
|
||||||
|
}
|
||||||
|
else if (!strcmp(name, "format/frame rate")
|
||||||
|
{
|
||||||
|
/* 24 */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively, you might like to parse iteratively.
|
Alternatively, you might like to parse iteratively.
|
||||||
@ -266,28 +288,31 @@ You'd use:
|
|||||||
```c
|
```c
|
||||||
void parse_object(cJSON *item)
|
void parse_object(cJSON *item)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0 ; i < cJSON_GetArraySize(item) ; i++)
|
for (i = 0; i < cJSON_GetArraySize(item); i++)
|
||||||
{
|
{
|
||||||
cJSON * subitem = cJSON_GetArrayItem(item, i);
|
cJSON *subitem = cJSON_GetArrayItem(item, i);
|
||||||
// handle subitem
|
// handle subitem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Or, for PROPER manual mode:
|
Or, for PROPER manual mode:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
void parse_object(cJSON * item)
|
void parse_object(cJSON *item)
|
||||||
{
|
{
|
||||||
cJSON *subitem = item->child;
|
cJSON *subitem = item->child;
|
||||||
while (subitem)
|
while (subitem)
|
||||||
{
|
{
|
||||||
// handle subitem
|
// handle subitem
|
||||||
if (subitem->child) parse_object(subitem->child);
|
if (subitem->child)
|
||||||
|
{
|
||||||
|
parse_object(subitem->child);
|
||||||
|
}
|
||||||
|
|
||||||
subitem = subitem->next;
|
subitem = subitem->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -303,19 +328,29 @@ 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?
|
For instance, suppose you wanted to build an array of objects?
|
||||||
|
|
||||||
```c
|
```c
|
||||||
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;
|
int i;
|
||||||
cJSON * prev, * root = cJSON_CreateArray();
|
cJSON *prev;
|
||||||
for (i = 0 ; i < 24 ; i++)
|
cJSON *root = cJSON_CreateArray();
|
||||||
{
|
for (i = 0; i < 24; i++)
|
||||||
if (!i) root->child = objects[i];
|
{
|
||||||
else prev->next = objects[i], objects[i]->prev = prev;
|
if (!i)
|
||||||
prev = objects[i];
|
{
|
||||||
}
|
root->child = objects[i];
|
||||||
return root;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prev->next = objects[i];
|
||||||
|
objects[i]->prev = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = objects[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return root;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -325,11 +360,11 @@ cJSON 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
|
You can attach the objects, as above, and later add children to each
|
||||||
of those objects.
|
of those objects.
|
||||||
|
|
||||||
As soon as you call cJSON_Print, it renders the structure to text.
|
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 `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,
|
the code, it'll load, parse and print a bunch of test files, also from [json.org](http://json.org),
|
||||||
which are more complex than I'd care to try and stash into a const char array[].
|
which are more complex than I'd care to try and stash into a `const char array[]`.
|
||||||
|
|
||||||
# Enjoy cJSON!
|
# Enjoy cJSON!
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user