Axeda Ready Demo for Freescale FRDM-KL46Z as accident alert system
Dependencies: FRDM_MMA8451Q KL46Z-USBHost MAG3110 SocketModem TSI mbed FATFileSystem
Fork of AxedaGo-Freescal_FRDM-KL46Z by
cJSON/README.txt@2:2f9019c5a9fc, 2014-07-02 (annotated)
- Committer:
- AxedaCorp
- Date:
- Wed Jul 02 19:57:37 2014 +0000
- Revision:
- 2:2f9019c5a9fc
- Parent:
- 0:65004368569c
ip switch
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AxedaCorp | 0:65004368569c | 1 | /* |
AxedaCorp | 0:65004368569c | 2 | Copyright (c) 2009 Dave Gamble |
AxedaCorp | 0:65004368569c | 3 | |
AxedaCorp | 0:65004368569c | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy |
AxedaCorp | 0:65004368569c | 5 | of this software and associated documentation files (the "Software"), to deal |
AxedaCorp | 0:65004368569c | 6 | in the Software without restriction, including without limitation the rights |
AxedaCorp | 0:65004368569c | 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
AxedaCorp | 0:65004368569c | 8 | copies of the Software, and to permit persons to whom the Software is |
AxedaCorp | 0:65004368569c | 9 | furnished to do so, subject to the following conditions: |
AxedaCorp | 0:65004368569c | 10 | |
AxedaCorp | 0:65004368569c | 11 | The above copyright notice and this permission notice shall be included in |
AxedaCorp | 0:65004368569c | 12 | all copies or substantial portions of the Software. |
AxedaCorp | 0:65004368569c | 13 | |
AxedaCorp | 0:65004368569c | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
AxedaCorp | 0:65004368569c | 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
AxedaCorp | 0:65004368569c | 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
AxedaCorp | 0:65004368569c | 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
AxedaCorp | 0:65004368569c | 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
AxedaCorp | 0:65004368569c | 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
AxedaCorp | 0:65004368569c | 20 | THE SOFTWARE. |
AxedaCorp | 0:65004368569c | 21 | */ |
AxedaCorp | 0:65004368569c | 22 | |
AxedaCorp | 0:65004368569c | 23 | Welcome to cJSON. |
AxedaCorp | 0:65004368569c | 24 | |
AxedaCorp | 0:65004368569c | 25 | cJSON aims to be the dumbest possible parser that you can get your job done with. |
AxedaCorp | 0:65004368569c | 26 | It's a single file of C, and a single header file. |
AxedaCorp | 0:65004368569c | 27 | |
AxedaCorp | 0:65004368569c | 28 | JSON is described best here: http://www.json.org/ |
AxedaCorp | 0:65004368569c | 29 | It's like XML, but fat-free. You use it to move data around, store things, or just |
AxedaCorp | 0:65004368569c | 30 | generally represent your program's state. |
AxedaCorp | 0:65004368569c | 31 | |
AxedaCorp | 0:65004368569c | 32 | |
AxedaCorp | 0:65004368569c | 33 | First up, how do I build? |
AxedaCorp | 0:65004368569c | 34 | Add cJSON.c to your project, and put cJSON.h somewhere in the header search path. |
AxedaCorp | 0:65004368569c | 35 | For example, to build the test app: |
AxedaCorp | 0:65004368569c | 36 | |
AxedaCorp | 0:65004368569c | 37 | gcc cJSON.c test.c -o test -lm |
AxedaCorp | 0:65004368569c | 38 | ./test |
AxedaCorp | 0:65004368569c | 39 | |
AxedaCorp | 0:65004368569c | 40 | |
AxedaCorp | 0:65004368569c | 41 | As a library, cJSON exists to take away as much legwork as it can, but not get in your way. |
AxedaCorp | 0:65004368569c | 42 | As a point of pragmatism (i.e. ignoring the truth), I'm going to say that you can use it |
AxedaCorp | 0:65004368569c | 43 | in one of two modes: Auto and Manual. Let's have a quick run-through. |
AxedaCorp | 0:65004368569c | 44 | |
AxedaCorp | 0:65004368569c | 45 | |
AxedaCorp | 0:65004368569c | 46 | I lifted some JSON from this page: http://www.json.org/fatfree.html |
AxedaCorp | 0:65004368569c | 47 | That page inspired me to write cJSON, which is a parser that tries to share the same |
AxedaCorp | 0:65004368569c | 48 | philosophy as JSON itself. Simple, dumb, out of the way. |
AxedaCorp | 0:65004368569c | 49 | |
AxedaCorp | 0:65004368569c | 50 | Some JSON: |
AxedaCorp | 0:65004368569c | 51 | { |
AxedaCorp | 0:65004368569c | 52 | "name": "Jack (\"Bee\") Nimble", |
AxedaCorp | 0:65004368569c | 53 | "format": { |
AxedaCorp | 0:65004368569c | 54 | "type": "rect", |
AxedaCorp | 0:65004368569c | 55 | "width": 1920, |
AxedaCorp | 0:65004368569c | 56 | "height": 1080, |
AxedaCorp | 0:65004368569c | 57 | "interlace": false, |
AxedaCorp | 0:65004368569c | 58 | "frame rate": 24 |
AxedaCorp | 0:65004368569c | 59 | } |
AxedaCorp | 0:65004368569c | 60 | } |
AxedaCorp | 0:65004368569c | 61 | |
AxedaCorp | 0:65004368569c | 62 | Assume that you got this from a file, a webserver, or magic JSON elves, whatever, |
AxedaCorp | 0:65004368569c | 63 | you have a char * to it. Everything is a cJSON struct. |
AxedaCorp | 0:65004368569c | 64 | Get it parsed: |
AxedaCorp | 0:65004368569c | 65 | cJSON *root = cJSON_Parse(my_json_string); |
AxedaCorp | 0:65004368569c | 66 | |
AxedaCorp | 0:65004368569c | 67 | This is an object. We're in C. We don't have objects. But we do have structs. |
AxedaCorp | 0:65004368569c | 68 | What's the framerate? |
AxedaCorp | 0:65004368569c | 69 | |
AxedaCorp | 0:65004368569c | 70 | cJSON *format = cJSON_GetObjectItem(root,"format"); |
AxedaCorp | 0:65004368569c | 71 | int framerate = cJSON_GetObjectItem(format,"frame rate")->valueint; |
AxedaCorp | 0:65004368569c | 72 | |
AxedaCorp | 0:65004368569c | 73 | |
AxedaCorp | 0:65004368569c | 74 | Want to change the framerate? |
AxedaCorp | 0:65004368569c | 75 | cJSON_GetObjectItem(format,"frame rate")->valueint=25; |
AxedaCorp | 0:65004368569c | 76 | |
AxedaCorp | 0:65004368569c | 77 | Back to disk? |
AxedaCorp | 0:65004368569c | 78 | char *rendered=cJSON_Print(root); |
AxedaCorp | 0:65004368569c | 79 | |
AxedaCorp | 0:65004368569c | 80 | Finished? Delete the root (this takes care of everything else). |
AxedaCorp | 0:65004368569c | 81 | cJSON_Delete(root); |
AxedaCorp | 0:65004368569c | 82 | |
AxedaCorp | 0:65004368569c | 83 | That's AUTO mode. If you're going to use Auto mode, you really ought to check pointers |
AxedaCorp | 0:65004368569c | 84 | before you dereference them. If you want to see how you'd build this struct in code? |
AxedaCorp | 0:65004368569c | 85 | cJSON *root,*fmt; |
AxedaCorp | 0:65004368569c | 86 | root=cJSON_CreateObject(); |
AxedaCorp | 0:65004368569c | 87 | cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble")); |
AxedaCorp | 0:65004368569c | 88 | cJSON_AddItemToObject(root, "format", fmt=cJSON_CreateObject()); |
AxedaCorp | 0:65004368569c | 89 | cJSON_AddStringToObject(fmt,"type", "rect"); |
AxedaCorp | 0:65004368569c | 90 | cJSON_AddNumberToObject(fmt,"width", 1920); |
AxedaCorp | 0:65004368569c | 91 | cJSON_AddNumberToObject(fmt,"height", 1080); |
AxedaCorp | 0:65004368569c | 92 | cJSON_AddFalseToObject (fmt,"interlace"); |
AxedaCorp | 0:65004368569c | 93 | cJSON_AddNumberToObject(fmt,"frame rate", 24); |
AxedaCorp | 0:65004368569c | 94 | |
AxedaCorp | 0:65004368569c | 95 | Hopefully we can agree that's not a lot of code? There's no overhead, no unnecessary setup. |
AxedaCorp | 0:65004368569c | 96 | Look at test.c for a bunch of nice examples, mostly all ripped off the json.org site, and |
AxedaCorp | 0:65004368569c | 97 | a few from elsewhere. |
AxedaCorp | 0:65004368569c | 98 | |
AxedaCorp | 0:65004368569c | 99 | What about manual mode? First up you need some detail. |
AxedaCorp | 0:65004368569c | 100 | Let's cover how the cJSON objects represent the JSON data. |
AxedaCorp | 0:65004368569c | 101 | cJSON doesn't distinguish arrays from objects in handling; just type. |
AxedaCorp | 0:65004368569c | 102 | Each cJSON has, potentially, a child, siblings, value, a name. |
AxedaCorp | 0:65004368569c | 103 | |
AxedaCorp | 0:65004368569c | 104 | The root object has: Object Type and a Child |
AxedaCorp | 0:65004368569c | 105 | The Child has name "name", with value "Jack ("Bee") Nimble", and a sibling: |
AxedaCorp | 0:65004368569c | 106 | Sibling has type Object, name "format", and a child. |
AxedaCorp | 0:65004368569c | 107 | That child has type String, name "type", value "rect", and a sibling: |
AxedaCorp | 0:65004368569c | 108 | Sibling has type Number, name "width", value 1920, and a sibling: |
AxedaCorp | 0:65004368569c | 109 | Sibling has type Number, name "height", value 1080, and a sibling: |
AxedaCorp | 0:65004368569c | 110 | Sibling hs type False, name "interlace", and a sibling: |
AxedaCorp | 0:65004368569c | 111 | Sibling has type Number, name "frame rate", value 24 |
AxedaCorp | 0:65004368569c | 112 | |
AxedaCorp | 0:65004368569c | 113 | Here's the structure: |
AxedaCorp | 0:65004368569c | 114 | typedef struct cJSON { |
AxedaCorp | 0:65004368569c | 115 | struct cJSON *next,*prev; |
AxedaCorp | 0:65004368569c | 116 | struct cJSON *child; |
AxedaCorp | 0:65004368569c | 117 | |
AxedaCorp | 0:65004368569c | 118 | int type; |
AxedaCorp | 0:65004368569c | 119 | |
AxedaCorp | 0:65004368569c | 120 | char *valuestring; |
AxedaCorp | 0:65004368569c | 121 | int valueint; |
AxedaCorp | 0:65004368569c | 122 | double valuedouble; |
AxedaCorp | 0:65004368569c | 123 | |
AxedaCorp | 0:65004368569c | 124 | char *string; |
AxedaCorp | 0:65004368569c | 125 | } cJSON; |
AxedaCorp | 0:65004368569c | 126 | |
AxedaCorp | 0:65004368569c | 127 | By default all values are 0 unless set by virtue of being meaningful. |
AxedaCorp | 0:65004368569c | 128 | |
AxedaCorp | 0:65004368569c | 129 | next/prev is a doubly linked list of siblings. next takes you to your sibling, |
AxedaCorp | 0:65004368569c | 130 | prev takes you back from your sibling to you. |
AxedaCorp | 0:65004368569c | 131 | Only objects and arrays have a "child", and it's the head of the doubly linked list. |
AxedaCorp | 0:65004368569c | 132 | A "child" entry will have prev==0, but next potentially points on. The last sibling has next=0. |
AxedaCorp | 0:65004368569c | 133 | The type expresses Null/True/False/Number/String/Array/Object, all of which are #defined in |
AxedaCorp | 0:65004368569c | 134 | cJSON.h |
AxedaCorp | 0:65004368569c | 135 | |
AxedaCorp | 0:65004368569c | 136 | A Number has valueint and valuedouble. If you're expecting an int, read valueint, if not read |
AxedaCorp | 0:65004368569c | 137 | valuedouble. |
AxedaCorp | 0:65004368569c | 138 | |
AxedaCorp | 0:65004368569c | 139 | Any entry which is in the linked list which is the child of an object will have a "string" |
AxedaCorp | 0:65004368569c | 140 | which is the "name" of the entry. When I said "name" in the above example, that's "string". |
AxedaCorp | 0:65004368569c | 141 | "string" is the JSON name for the 'variable name' if you will. |
AxedaCorp | 0:65004368569c | 142 | |
AxedaCorp | 0:65004368569c | 143 | Now you can trivially walk the lists, recursively, and parse as you please. |
AxedaCorp | 0:65004368569c | 144 | You can invoke cJSON_Parse to get cJSON to parse for you, and then you can take |
AxedaCorp | 0:65004368569c | 145 | the root object, and traverse the structure (which is, formally, an N-tree), |
AxedaCorp | 0:65004368569c | 146 | and tokenise as you please. If you wanted to build a callback style parser, this is how |
AxedaCorp | 0:65004368569c | 147 | you'd do it (just an example, since these things are very specific): |
AxedaCorp | 0:65004368569c | 148 | |
AxedaCorp | 0:65004368569c | 149 | void parse_and_callback(cJSON *item,const char *prefix) |
AxedaCorp | 0:65004368569c | 150 | { |
AxedaCorp | 0:65004368569c | 151 | while (item) |
AxedaCorp | 0:65004368569c | 152 | { |
AxedaCorp | 0:65004368569c | 153 | char *newprefix=malloc(strlen(prefix)+strlen(item->name)+2); |
AxedaCorp | 0:65004368569c | 154 | sprintf(newprefix,"%s/%s",prefix,item->name); |
AxedaCorp | 0:65004368569c | 155 | int dorecurse=callback(newprefix, item->type, item); |
AxedaCorp | 0:65004368569c | 156 | if (item->child && dorecurse) parse_and_callback(item->child,newprefix); |
AxedaCorp | 0:65004368569c | 157 | item=item->next; |
AxedaCorp | 0:65004368569c | 158 | free(newprefix); |
AxedaCorp | 0:65004368569c | 159 | } |
AxedaCorp | 0:65004368569c | 160 | } |
AxedaCorp | 0:65004368569c | 161 | |
AxedaCorp | 0:65004368569c | 162 | The prefix process will build you a separated list, to simplify your callback handling. |
AxedaCorp | 0:65004368569c | 163 | The 'dorecurse' flag would let the callback decide to handle sub-arrays on it's own, or |
AxedaCorp | 0:65004368569c | 164 | let you invoke it per-item. For the item above, your callback might look like this: |
AxedaCorp | 0:65004368569c | 165 | |
AxedaCorp | 0:65004368569c | 166 | int callback(const char *name,int type,cJSON *item) |
AxedaCorp | 0:65004368569c | 167 | { |
AxedaCorp | 0:65004368569c | 168 | if (!strcmp(name,"name")) { /* populate name */ } |
AxedaCorp | 0:65004368569c | 169 | else if (!strcmp(name,"format/type") { /* handle "rect" */ } |
AxedaCorp | 0:65004368569c | 170 | else if (!strcmp(name,"format/width") { /* 800 */ } |
AxedaCorp | 0:65004368569c | 171 | else if (!strcmp(name,"format/height") { /* 600 */ } |
AxedaCorp | 0:65004368569c | 172 | else if (!strcmp(name,"format/interlace") { /* false */ } |
AxedaCorp | 0:65004368569c | 173 | else if (!strcmp(name,"format/frame rate") { /* 24 */ } |
AxedaCorp | 0:65004368569c | 174 | return 1; |
AxedaCorp | 0:65004368569c | 175 | } |
AxedaCorp | 0:65004368569c | 176 | |
AxedaCorp | 0:65004368569c | 177 | Alternatively, you might like to parse iteratively. |
AxedaCorp | 0:65004368569c | 178 | You'd use: |
AxedaCorp | 0:65004368569c | 179 | |
AxedaCorp | 0:65004368569c | 180 | void parse_object(cJSON *item) |
AxedaCorp | 0:65004368569c | 181 | { |
AxedaCorp | 0:65004368569c | 182 | int i; for (i=0;i<cJSON_GetArraySize(item);i++) |
AxedaCorp | 0:65004368569c | 183 | { |
AxedaCorp | 0:65004368569c | 184 | cJSON *subitem=cJSON_GetArrayItem(item,i); |
AxedaCorp | 0:65004368569c | 185 | // handle subitem. |
AxedaCorp | 0:65004368569c | 186 | } |
AxedaCorp | 0:65004368569c | 187 | } |
AxedaCorp | 0:65004368569c | 188 | |
AxedaCorp | 0:65004368569c | 189 | Or, for PROPER manual mode: |
AxedaCorp | 0:65004368569c | 190 | |
AxedaCorp | 0:65004368569c | 191 | void parse_object(cJSON *item) |
AxedaCorp | 0:65004368569c | 192 | { |
AxedaCorp | 0:65004368569c | 193 | cJSON *subitem=item->child; |
AxedaCorp | 0:65004368569c | 194 | while (subitem) |
AxedaCorp | 0:65004368569c | 195 | { |
AxedaCorp | 0:65004368569c | 196 | // handle subitem |
AxedaCorp | 0:65004368569c | 197 | if (subitem->child) parse_object(subitem->child); |
AxedaCorp | 0:65004368569c | 198 | |
AxedaCorp | 0:65004368569c | 199 | subitem=subitem->next; |
AxedaCorp | 0:65004368569c | 200 | } |
AxedaCorp | 0:65004368569c | 201 | } |
AxedaCorp | 0:65004368569c | 202 | |
AxedaCorp | 0:65004368569c | 203 | Of course, this should look familiar, since this is just a stripped-down version |
AxedaCorp | 0:65004368569c | 204 | of the callback-parser. |
AxedaCorp | 0:65004368569c | 205 | |
AxedaCorp | 0:65004368569c | 206 | This should cover most uses you'll find for parsing. The rest should be possible |
AxedaCorp | 0:65004368569c | 207 | to infer.. and if in doubt, read the source! There's not a lot of it! ;) |
AxedaCorp | 0:65004368569c | 208 | |
AxedaCorp | 0:65004368569c | 209 | |
AxedaCorp | 0:65004368569c | 210 | In terms of constructing JSON data, the example code above is the right way to do it. |
AxedaCorp | 0:65004368569c | 211 | You can, of course, hand your sub-objects to other functions to populate. |
AxedaCorp | 0:65004368569c | 212 | Also, if you find a use for it, you can manually build the objects. |
AxedaCorp | 0:65004368569c | 213 | For instance, suppose you wanted to build an array of objects? |
AxedaCorp | 0:65004368569c | 214 | |
AxedaCorp | 0:65004368569c | 215 | cJSON *objects[24]; |
AxedaCorp | 0:65004368569c | 216 | |
AxedaCorp | 0:65004368569c | 217 | cJSON *Create_array_of_anything(cJSON **items,int num) |
AxedaCorp | 0:65004368569c | 218 | { |
AxedaCorp | 0:65004368569c | 219 | int i;cJSON *prev, *root=cJSON_CreateArray(); |
AxedaCorp | 0:65004368569c | 220 | for (i=0;i<24;i++) |
AxedaCorp | 0:65004368569c | 221 | { |
AxedaCorp | 0:65004368569c | 222 | if (!i) root->child=objects[i]; |
AxedaCorp | 0:65004368569c | 223 | else prev->next=objects[i], objects[i]->prev=prev; |
AxedaCorp | 0:65004368569c | 224 | prev=objects[i]; |
AxedaCorp | 0:65004368569c | 225 | } |
AxedaCorp | 0:65004368569c | 226 | return root; |
AxedaCorp | 0:65004368569c | 227 | } |
AxedaCorp | 0:65004368569c | 228 | |
AxedaCorp | 0:65004368569c | 229 | and simply: Create_array_of_anything(objects,24); |
AxedaCorp | 0:65004368569c | 230 | |
AxedaCorp | 0:65004368569c | 231 | cJSON doesn't make any assumptions about what order you create things in. |
AxedaCorp | 0:65004368569c | 232 | You can attach the objects, as above, and later add children to each |
AxedaCorp | 0:65004368569c | 233 | of those objects. |
AxedaCorp | 0:65004368569c | 234 | |
AxedaCorp | 0:65004368569c | 235 | As soon as you call cJSON_Print, it renders the structure to text. |
AxedaCorp | 0:65004368569c | 236 | |
AxedaCorp | 0:65004368569c | 237 | |
AxedaCorp | 0:65004368569c | 238 | |
AxedaCorp | 0:65004368569c | 239 | The test.c code shows how to handle a bunch of typical cases. If you uncomment |
AxedaCorp | 0:65004368569c | 240 | the code, it'll load, parse and print a bunch of test files, also from json.org, |
AxedaCorp | 0:65004368569c | 241 | which are more complex than I'd care to try and stash into a const char array[]. |
AxedaCorp | 0:65004368569c | 242 | |
AxedaCorp | 0:65004368569c | 243 | |
AxedaCorp | 0:65004368569c | 244 | Enjoy cJSON! |
AxedaCorp | 0:65004368569c | 245 | |
AxedaCorp | 0:65004368569c | 246 | |
AxedaCorp | 0:65004368569c | 247 | - Dave Gamble, Aug 2009 |
AxedaCorp | 0:65004368569c | 248 |