STM32-cJSON庫的打包和解析


這幾天使用了一下JSON在STM32103平台上的使用,還是很好用的,在此記錄下。

JSON是啥我也不總結了,就是直觀的看起來是一個有格式的字符串,看起來非常清楚明白,有點像Python中的dicitionary的意思,鍵值對,詳細的可以看此鏈接http://www.cnblogs.com/catgatp/p/6380030.html。實際使用的過程中主要就是“打包”和“解析”。下面直接來代碼。

 

 1 char * Status_to_cJSON( char * cJSONROOM, ROBOStatus_TypeDef status)//傳入一個變量的指針,這里cJSONROOM是一個全局變量(一個提前規定大小的字符數組),用來存放轉換之后的JSON字符串
 2 
 3 {
 4 
 5       char *result;
 6 
 7       cJSON *root,*subroot;//新建兩個cJSON的對象指針
 8 
 9       root=cJSON_CreateObject();//創建一個機器人狀態的JSON對象
10 
11       subroot=cJSON_CreateObject();//subroot是下面的一個嵌入對象
12 
13       cJSON_AddStringToObject(subroot,"RunStatus",status.RunStatus);//將status.RunStatus的值賦值到subroot下面一個叫RunStatus的變量。
14 
15       cJSON_AddStringToObject(subroot,"CurrentTime",status.CurrentTime);
16 
17 //同上
18 
19   cJSON_AddNumberToObject(subroot,"CurrentPosition",status.CurrentPositiont);
20 
21 //將位置信息賦值到subroot下面一個叫CurrentPosition的變量,注意此處為Number類型
22 
23       cJSON_AddNumberToObject(subroot,"CurrentSpeed",status.CurrentSpeed);
24 
25       cJSON_AddNumberToObject(subroot,"RunningCount",status.RunningCount);      
26 
27       cJSON_AddNumberToObject(subroot,"CurrentTemp",status.CurrentTemp);
28 
29      cJSON_AddNumberToObject(subroot,"CurrentVoltage",status.CurrentVoltage);      
30 
31       cJSON_AddNumberToObject(subroot,"CurrentAmp",status.CurrentAmp);
32 
33       cJSON_AddNumberToObject(subroot,"CurrentDir",status.CurrentDir);   
34 
35 cJSON_AddNumberToObject(subroot,"ControlSystemEnergy",status.ControlSystemEnergy);
36 
37 cJSON_AddNumberToObject(subroot,"DynamicSystemEnergy",status.DynamicSystemEnergy);
38 
39    cJSON_AddItemToObject(root, "RobotStatus", subroot);
40 
41       result=cJSON_PrintUnformatted(root);//生成JSONC字符串,注意可以用cJSON_Print()格式的,就是人眼看着好看一點,就是有點占用存儲空間
42 
43       strcpy(cJSONROOM,result);//將轉換的結果字符串賦值給傳入的全局變量
44 
45       cJSON_Delete(root);//最后將root根節點刪除
46 
47       myfree(result);//釋放result的空間,必須要有,要不然內存里會失去一段空間,最后系統崩潰
48 
49       return cJSONROOM;//不要指望着返回一個局部變量的地址,這是非常危險的,因為函數調用完畢后這個地址指向的內容就消失了。所以這個函數在設計的時候返回了一個全局變量的地址。
50 
51 }   

 

注意:malloc在STM32平台上使用的時候需要改動一下,關於內存操作的改動見下面的代碼。使用字符數組會提高程序的可靠性,之前一直用字符指針,可能沒有用好,中途會掛掉,后來發現提前建立一個數組,在這段空間進行數據的操作還是比較穩定的。

  1 #include "malloc.h"
  2 
  3 //內存池(4字節對齊)
  4 __align(4) u8 membase[MEM_MAX_SIZE];                                                    //內部SRAM內存池
  5 //內存管理表
  6 u16 memmapbase[MEM_ALLOC_TABLE_SIZE];                                                    //內部SRAM內存池MAP
  7 //內存管理參數       
  8 const u32 memtblsize = MEM_ALLOC_TABLE_SIZE;        //內存表大小
  9 const u32 memblksize = MEM_BLOCK_SIZE;                    //內存分塊大小
 10 const u32 memsize    = MEM_MAX_SIZE;                            //內存總大小
 11 
 12 
 13 //內存管理控制器
 14 struct _m_mallco_dev mallco_dev=
 15 {
 16     mem_init,                //內存初始化
 17     mem_perused,      //內存使用率
 18     membase,            //內存池
 19     memmapbase,     //內存管理狀態表
 20     0,                        //內存管理未就緒
 21 };
 22 
 23 //復制內存
 24 //*des:目的地址
 25 //*src:源地址
 26 //n:需要復制的內存長度(字節為單位)
 27 void mymemcpy(void *des,void *src,u32 n)  
 28 {  
 29   u8 *xdes=des;
 30     u8 *xsrc=src; 
 31   while(n--)*xdes++=*xsrc++;  
 32 }  
 33 
 34 //設置內存
 35 //*s:內存首地址
 36 //c :要設置的值
 37 //count:需要設置的內存大小(字節為單位)
 38 void mymemset(void *s,u8 c,u32 count)  
 39 {  
 40     u8 *xs = s;  
 41     while(count--)*xs++=c;  
 42 }    
 43 
 44 //內存管理初始化  
 45 //memx:所屬內存塊
 46 void mem_init(void)  
 47 {  
 48   mymemset(mallco_dev.memmap, 0,memtblsize*2);//內存狀態表數據清零  
 49     mymemset(mallco_dev.membase, 0,memsize);    //內存池所有數據清零  
 50     mallco_dev.memrdy=1;                                //內存管理初始化OK  
 51 } 
 52  
 53 //獲取內存使用率
 54 //memx:所屬內存塊
 55 //返回值:使用率(0~100)
 56 u8 mem_perused(void)  
 57 {  
 58     u32 used=0;  
 59     u32 i;  
 60     for(i=0;i<memtblsize;i++)  
 61     {  
 62         if(mallco_dev.memmap[i])used++; 
 63     } 
 64     return (used*100)/(memtblsize);  
 65 }  
 66 
 67 //內存分配(內部調用)
 68 //memx:所屬內存塊
 69 //size:要分配的內存大小(字節)
 70 //返回值:0XFFFFFFFF,代表錯誤;其他,內存偏移地址 
 71 u32 mem_malloc(u32 size)  
 72 {  
 73     signed long offset=0;  
 74     u16 nmemb;    //需要的內存塊數  
 75     u16 cmemb=0;//連續空內存塊數
 76     u32 i;  
 77     if(!mallco_dev.memrdy)mallco_dev.init();//未初始化,先執行初始化 
 78     if(size==0)return 0XFFFFFFFF;//不需要分配
 79 
 80     nmemb=size/memblksize;      //獲取需要分配的連續內存塊數
 81     if(size%memblksize)nmemb++;  
 82     for(offset=memtblsize-1;offset>=0;offset--)//搜索整個內存控制區  
 83     {     
 84         if(!mallco_dev.memmap[offset])cmemb++;//連續空內存塊數增加
 85         else cmemb=0;                                //連續內存塊清零
 86         if(cmemb==nmemb)                            //找到了連續nmemb個空內存塊
 87         {
 88             for(i=0;i<nmemb;i++)                      //標注內存塊非空 
 89             {  
 90                 mallco_dev.memmap[offset+i]=nmemb;  
 91             }  
 92             return (offset*memblksize);//返回偏移地址  
 93         }
 94     }  
 95     return 0XFFFFFFFF;//未找到符合分配條件的內存塊  
 96 }  
 97 
 98 //釋放內存(內部調用) 
 99 //memx:所屬內存塊
100 //offset:內存地址偏移
101 //返回值:0,釋放成功;1,釋放失敗;  
102 u8 mem_free(u32 offset)  
103 {  
104     int i;  
105     if(!mallco_dev.memrdy)//未初始化,先執行初始化
106     {
107         mallco_dev.init();    
108         return 1;//未初始化  
109     }  
110     if(offset<memsize)//偏移在內存池內. 
111     {  
112         int index=offset/memblksize;            //偏移所在內存塊號碼  
113         int nmemb=mallco_dev.memmap[index];    //內存塊數量
114         for(i=0;i<nmemb;i++)                          //內存塊清零
115         {  
116             mallco_dev.memmap[index+i]=0;  
117         }  
118         return 0;  
119     }else return 2;//偏移超區了.  
120 }  
121 
122 //釋放內存(外部調用) 
123 //memx:所屬內存塊
124 //ptr:內存首地址 
125 void myfree(void *ptr)  
126 {  
127     u32 offset;  
128     if(ptr==NULL)return;//地址為0.  
129      offset=(u32)ptr-(u32)mallco_dev.membase;  
130     mem_free(offset);//釋放內存     
131 }
132 
133 //分配內存(外部調用)
134 //memx:所屬內存塊
135 //size:內存大小(字節)
136 //返回值:分配到的內存首地址.
137 void *mymalloc(u32 size)  
138 {  
139     u32 offset;                                            
140     offset=mem_malloc(size);                            
141     if(offset==0XFFFFFFFF)return NULL;  
142     else return (void*)((u32)mallco_dev.membase+offset);  
143 }  
144 
145 //重新分配內存(外部調用)
146 //memx:所屬內存塊
147 //*ptr:舊內存首地址
148 //size:要分配的內存大小(字節)
149 //返回值:新分配到的內存首地址.
150 void *myrealloc(void *ptr,u32 size)  
151 {  
152     u32 offset;  
153     offset=mem_malloc(size);  
154     if(offset==0XFFFFFFFF)return NULL;     
155     else  
156     {                                         
157         mymemcpy((void*)((u32)mallco_dev.membase+offset),ptr,size);    //拷貝舊內存內容到新內存   
158         myfree(ptr);                                                        //釋放舊內存
159         return (void*)((u32)mallco_dev.membase+offset);                  //返回新內存首地址
160     }  
161 } 

malloc.h內容如下:

 1 #ifndef __MALLOC_H
 2 #define __MALLOC_H
 3 #include "stm32f10x.h"
 4   
 5 #ifndef NULL
 6 #define NULL 0
 7 #endif
 8 
 9 #define MEM_BLOCK_SIZE              32                                      //內存塊大小為32字節
10 #define MEM_MAX_SIZE                16*1024                                  //最大管理內存 2K
11 #define MEM_ALLOC_TABLE_SIZE    MEM_MAX_SIZE/MEM_BLOCK_SIZE //內存表大小
12          
13 //內存管理控制器
14 struct _m_mallco_dev
15 {
16     void (*init)(void);                    //初始化
17     u8   (*perused)(void);                      //內存使用率
18     u8       *membase;                    //內存池
19     u16   *memmap;                     //內存管理狀態表
20     u8     memrdy;                         //內存管理是否就緒
21 };
22 
23 extern struct _m_mallco_dev mallco_dev;     //在mallco.c里面定義
24 
25 void mymemset(void *s,u8 c,u32 count);     //設置內存
26 void mymemcpy(void *des,void *src,u32 n);//復制內存 
27 
28 void mem_init(void);                     //內存管理初始化函數
29 u32 mem_malloc(u32 size);         //內存分配
30 u8 mem_free(u32 offset);         //內存釋放
31 u8 mem_perused(void);                 //獲得內存使用率 
32 ////////////////////////////////////////////////////////////////////////////////
33 //用戶調用函數
34 void myfree(void *ptr);              //內存釋放
35 void *mymalloc(u32 size);            //內存分配
36 void *myrealloc(void *ptr,u32 size);//重新分配內存
37 #endif

cJSON.c的內容也全在下面

  1 /*
  2   Copyright (c) 2009 Dave Gamble
  3 
  4   Permission is hereby granted, free of charge, to any person obtaining a copy
  5   of this software and associated documentation files (the "Software"), to deal
  6   in the Software without restriction, including without limitation the rights
  7   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8   copies of the Software, and to permit persons to whom the Software is
  9   furnished to do so, subject to the following conditions:
 10 
 11   The above copyright notice and this permission notice shall be included in
 12   all copies or substantial portions of the Software.
 13 
 14   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 15   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 16   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 17   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 18   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 19   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 20   THE SOFTWARE.
 21 */
 22 
 23 /* cJSON */
 24 /* JSON parser in C. */
 25 
 26 #include <string.h>
 27 #include <stdio.h>
 28 #include <math.h>
 29 #include <stdlib.h>
 30 #include <float.h>
 31 #include <limits.h>
 32 #include <ctype.h>
 33 #include "cJSON.h"
 34 
 35 #include "malloc.h"
 36 
 37 static const char *ep;
 38 
 39 const char *cJSON_GetErrorPtr(void) {return ep;}
 40 
 41 static int cJSON_strcasecmp(const char *s1,const char *s2)
 42 {
 43     if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
 44     for(; tolower(*s1) == tolower(*s2); ++s1, ++s2)    if(*s1 == 0)    return 0;
 45     return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
 46 }
 47 
 48 static void *(*cJSON_malloc)(size_t sz) = mymalloc;
 49 static void (*cJSON_free)(void *ptr) = myfree;
 50 
 51 static char* cJSON_strdup(const char* str)
 52 {
 53       size_t len;
 54       char* copy;
 55 
 56       len = strlen(str) + 1;
 57       if (!(copy = (char*)cJSON_malloc(len))) return 0;
 58       memcpy(copy,str,len);
 59       return copy;
 60 }
 61 
 62 void cJSON_InitHooks(cJSON_Hooks* hooks)
 63 {
 64     if (!hooks) { /* Reset hooks */
 65         cJSON_malloc = malloc;
 66         cJSON_free = free;
 67         return;
 68     }
 69 
 70     cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
 71     cJSON_free     = (hooks->free_fn)?hooks->free_fn:free;
 72 }
 73 
 74 /* Internal constructor. */
 75 static cJSON *cJSON_New_Item(void)
 76 {
 77     cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
 78     if (node) memset(node,0,sizeof(cJSON));
 79     return node;
 80 }
 81 
 82 /* Delete a cJSON structure. */
 83 void cJSON_Delete(cJSON *c)
 84 {
 85     cJSON *next;
 86     while (c)
 87     {
 88         next=c->next;
 89         if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
 90         if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
 91         if (c->string) cJSON_free(c->string);
 92         cJSON_free(c);
 93         c=next;
 94     }
 95 }
 96 
 97 /* Parse the input text to generate a number, and populate the result into item. */
 98 static const char *parse_number(cJSON *item,const char *num)
 99 {
100     double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
101 
102     if (*num=='-') sign=-1,num++;    /* Has sign? */
103     if (*num=='0') num++;            /* is zero */
104     if (*num>='1' && *num<='9')    do    n=(n*10.0)+(*num++ -'0');    while (*num>='0' && *num<='9');    /* Number? */
105     if (*num=='.' && num[1]>='0' && num[1]<='9') {num++;        do    n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');}    /* Fractional part? */
106     if (*num=='e' || *num=='E')        /* Exponent? */
107     {    num++;if (*num=='+') num++;    else if (*num=='-') signsubscale=-1,num++;        /* With sign? */
108         while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0');    /* Number? */
109     }
110 
111     n=sign*n*pow(10.0,(scale+subscale*signsubscale));    /* number = +/- number.fraction * 10^+/- exponent */
112     
113     item->valuedouble=n;
114     item->valueint=(int)n;
115     item->type=cJSON_Number;
116     return num;
117 }
118 
119 /* Render the number nicely from the given item into a string. */
120 static char *print_number(cJSON *item)
121 {
122     char *str;
123     double d=item->valuedouble;
124     if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
125     {
126         str=(char*)cJSON_malloc(21);    /* 2^64+1 can be represented in 21 chars. */
127         if (str) sprintf(str,"%d",item->valueint);
128     }
129     else
130     {
131         str=(char*)cJSON_malloc(64);    /* This is a nice tradeoff. */
132         if (str)
133         {
134             if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
135             else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)            sprintf(str,"%e",d);
136             else                                                sprintf(str,"%f",d);
137         }
138     }
139     return str;
140 }
141 
142 static unsigned parse_hex4(const char *str)
143 {
144     unsigned h=0;
145     if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
146     h=h<<4;str++;
147     if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
148     h=h<<4;str++;
149     if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
150     h=h<<4;str++;
151     if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
152     return h;
153 }
154 
155 /* Parse the input text into an unescaped cstring, and populate item. */
156 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
157 static const char *parse_string(cJSON *item,const char *str)
158 {
159     const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
160     if (*str!='\"') {ep=str;return 0;}    /* not a string! */
161     
162     while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++;    /* Skip escaped quotes. */
163     
164     out=(char*)cJSON_malloc(len+1);    /* This is how long we need for the string, roughly. */
165     if (!out) return 0;
166     
167     ptr=str+1;ptr2=out;
168     while (*ptr!='\"' && *ptr)
169     {
170         if (*ptr!='\\') *ptr2++=*ptr++;
171         else
172         {
173             ptr++;
174             switch (*ptr)
175             {
176                 case 'b': *ptr2++='\b';    break;
177                 case 'f': *ptr2++='\f';    break;
178                 case 'n': *ptr2++='\n';    break;
179                 case 'r': *ptr2++='\r';    break;
180                 case 't': *ptr2++='\t';    break;
181                 case 'u':     /* transcode utf16 to utf8. */
182                     uc=parse_hex4(ptr+1);ptr+=4;    /* get the unicode char. */
183 
184                     if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)    break;    /* check for invalid.    */
185 
186                     if (uc>=0xD800 && uc<=0xDBFF)    /* UTF16 surrogate pairs.    */
187                     {
188                         if (ptr[1]!='\\' || ptr[2]!='u')    break;    /* missing second-half of surrogate.    */
189                         uc2=parse_hex4(ptr+3);ptr+=6;
190                         if (uc2<0xDC00 || uc2>0xDFFF)        break;    /* invalid second-half of surrogate.    */
191                         uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
192                     }
193 
194                     len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
195                     
196                     switch (len) {
197                         case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
198                         case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
199                         case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
200                         case 1: *--ptr2 =(uc | firstByteMark[len]);
201                     }
202                     ptr2+=len;
203                     break;
204                 default:  *ptr2++=*ptr; break;
205             }
206             ptr++;
207         }
208     }
209     *ptr2=0;
210     if (*ptr=='\"') ptr++;
211     item->valuestring=out;
212     item->type=cJSON_String;
213     return ptr;
214 }
215 
216 /* Render the cstring provided to an escaped version that can be printed. */
217 static char *print_string_ptr(const char *str)
218 {
219     const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
220     
221     if (!str) return cJSON_strdup("");
222     ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
223     
224     out=(char*)cJSON_malloc(len+3);
225     if (!out) return 0;
226 
227     ptr2=out;ptr=str;
228     *ptr2++='\"';
229     while (*ptr)
230     {
231         if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
232         else
233         {
234             *ptr2++='\\';
235             switch (token=*ptr++)
236             {
237                 case '\\':    *ptr2++='\\';    break;
238                 case '\"':    *ptr2++='\"';    break;
239                 case '\b':    *ptr2++='b';    break;
240                 case '\f':    *ptr2++='f';    break;
241                 case '\n':    *ptr2++='n';    break;
242                 case '\r':    *ptr2++='r';    break;
243                 case '\t':    *ptr2++='t';    break;
244                 default: sprintf(ptr2,"u%04x",token);ptr2+=5;    break;    /* escape and print */
245             }
246         }
247     }
248     *ptr2++='\"';*ptr2++=0;
249     return out;
250 }
251 /* Invote print_string_ptr (which is useful) on an item. */
252 static char *print_string(cJSON *item)    {return print_string_ptr(item->valuestring);}
253 
254 /* Predeclare these prototypes. */
255 static const char *parse_value(cJSON *item,const char *value);
256 static char *print_value(cJSON *item,int depth,int fmt);
257 static const char *parse_array(cJSON *item,const char *value);
258 static char *print_array(cJSON *item,int depth,int fmt);
259 static const char *parse_object(cJSON *item,const char *value);
260 static char *print_object(cJSON *item,int depth,int fmt);
261 
262 /* Utility to jump whitespace and cr/lf */
263 static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
264 
265 /* Parse an object - create a new root, and populate. */
266 cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
267 {
268     const char *end=0;
269     cJSON *c=cJSON_New_Item();
270     ep=0;
271     if (!c) return 0;       /* memory fail */
272 
273     end=parse_value(c,skip(value));
274     if (!end)    {cJSON_Delete(c);return 0;}    /* parse failure. ep is set. */
275 
276     /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
277     if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
278     if (return_parse_end) *return_parse_end=end;
279     return c;
280 }
281 /* Default options for cJSON_Parse */
282 cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
283 
284 /* Render a cJSON item/entity/structure to text. */
285 char *cJSON_Print(cJSON *item)                {return print_value(item,0,1);}
286 char *cJSON_PrintUnformatted(cJSON *item)    {return print_value(item,0,0);}
287 
288 /* Parser core - when encountering text, process appropriately. */
289 static const char *parse_value(cJSON *item,const char *value)
290 {
291     if (!value)                        return 0;    /* Fail on null. */
292     if (!strncmp(value,"null",4))    { item->type=cJSON_NULL;  return value+4; }
293     if (!strncmp(value,"false",5))    { item->type=cJSON_False; return value+5; }
294     if (!strncmp(value,"true",4))    { item->type=cJSON_True; item->valueint=1;    return value+4; }
295     if (*value=='\"')                { return parse_string(item,value); }
296     if (*value=='-' || (*value>='0' && *value<='9'))    { return parse_number(item,value); }
297     if (*value=='[')                { return parse_array(item,value); }
298     if (*value=='{')                { return parse_object(item,value); }
299 
300     ep=value;return 0;    /* failure. */
301 }
302 
303 /* Render a value to text. */
304 static char *print_value(cJSON *item,int depth,int fmt)
305 {
306     char *out=0;
307     if (!item) return 0;
308     switch ((item->type)&255)
309     {
310         case cJSON_NULL:    out=cJSON_strdup("null");    break;
311         case cJSON_False:    out=cJSON_strdup("false");break;
312         case cJSON_True:    out=cJSON_strdup("true"); break;
313         case cJSON_Number:    out=print_number(item);break;
314         case cJSON_String:    out=print_string(item);break;
315         case cJSON_Array:    out=print_array(item,depth,fmt);break;
316         case cJSON_Object:    out=print_object(item,depth,fmt);break;
317     }
318     return out;
319 }
320 
321 /* Build an array from input text. */
322 static const char *parse_array(cJSON *item,const char *value)
323 {
324     cJSON *child;
325     if (*value!='[')    {ep=value;return 0;}    /* not an array! */
326 
327     item->type=cJSON_Array;
328     value=skip(value+1);
329     if (*value==']') return value+1;    /* empty array. */
330 
331     item->child=child=cJSON_New_Item();
332     if (!item->child) return 0;         /* memory fail */
333     value=skip(parse_value(child,skip(value)));    /* skip any spacing, get the value. */
334     if (!value) return 0;
335 
336     while (*value==',')
337     {
338         cJSON *new_item;
339         if (!(new_item=cJSON_New_Item())) return 0;     /* memory fail */
340         child->next=new_item;new_item->prev=child;child=new_item;
341         value=skip(parse_value(child,skip(value+1)));
342         if (!value) return 0;    /* memory fail */
343     }
344 
345     if (*value==']') return value+1;    /* end of array */
346     ep=value;return 0;    /* malformed. */
347 }
348 
349 /* Render an array to text */
350 static char *print_array(cJSON *item,int depth,int fmt)
351 {
352     char **entries;
353     char *out=0,*ptr,*ret;int len=5;
354     cJSON *child=item->child;
355     int numentries=0,i=0,fail=0;
356     
357     /* How many entries in the array? */
358     while (child) numentries++,child=child->next;
359     /* Explicitly handle numentries==0 */
360     if (!numentries)
361     {
362         out=(char*)cJSON_malloc(3);
363         if (out) strcpy(out,"[]");
364         return out;
365     }
366     /* Allocate an array to hold the values for each */
367     entries=(char**)cJSON_malloc(numentries*sizeof(char*));
368     if (!entries) return 0;
369     memset(entries,0,numentries*sizeof(char*));
370     /* Retrieve all the results: */
371     child=item->child;
372     while (child && !fail)
373     {
374         ret=print_value(child,depth+1,fmt);
375         entries[i++]=ret;
376         if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
377         child=child->next;
378     }
379     
380     /* If we didn't fail, try to malloc the output string */
381     if (!fail) out=(char*)cJSON_malloc(len);
382     /* If that fails, we fail. */
383     if (!out) fail=1;
384 
385     /* Handle failure. */
386     if (fail)
387     {
388         for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
389         cJSON_free(entries);
390         return 0;
391     }
392     
393     /* Compose the output array. */
394     *out='[';
395     ptr=out+1;*ptr=0;
396     for (i=0;i<numentries;i++)
397     {
398         strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
399         if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
400         cJSON_free(entries[i]);
401     }
402     cJSON_free(entries);
403     *ptr++=']';*ptr++=0;
404     return out;    
405 }
406 
407 /* Build an object from the text. */
408 static const char *parse_object(cJSON *item,const char *value)
409 {
410     cJSON *child;
411     if (*value!='{')    {ep=value;return 0;}    /* not an object! */
412     
413     item->type=cJSON_Object;
414     value=skip(value+1);
415     if (*value=='}') return value+1;    /* empty array. */
416     
417     item->child=child=cJSON_New_Item();
418     if (!item->child) return 0;
419     value=skip(parse_string(child,skip(value)));
420     if (!value) return 0;
421     child->string=child->valuestring;child->valuestring=0;
422     if (*value!=':') {ep=value;return 0;}    /* fail! */
423     value=skip(parse_value(child,skip(value+1)));    /* skip any spacing, get the value. */
424     if (!value) return 0;
425     
426     while (*value==',')
427     {
428         cJSON *new_item;
429         if (!(new_item=cJSON_New_Item()))    return 0; /* memory fail */
430         child->next=new_item;new_item->prev=child;child=new_item;
431         value=skip(parse_string(child,skip(value+1)));
432         if (!value) return 0;
433         child->string=child->valuestring;child->valuestring=0;
434         if (*value!=':') {ep=value;return 0;}    /* fail! */
435         value=skip(parse_value(child,skip(value+1)));    /* skip any spacing, get the value. */
436         if (!value) return 0;
437     }
438     
439     if (*value=='}') return value+1;    /* end of array */
440     ep=value;return 0;    /* malformed. */
441 }
442 
443 /* Render an object to text. */
444 static char *print_object(cJSON *item,int depth,int fmt)
445 {
446     char **entries=0,**names=0;
447     char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
448     cJSON *child=item->child;
449     int numentries=0,fail=0;
450     /* Count the number of entries. */
451     while (child) numentries++,child=child->next;
452     /* Explicitly handle empty object case */
453     if (!numentries)
454     {
455         out=(char*)cJSON_malloc(fmt?depth+4:3);
456         if (!out)    return 0;
457         ptr=out;*ptr++='{';
458         if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
459         *ptr++='}';*ptr++=0;
460         return out;
461     }
462     /* Allocate space for the names and the objects */
463     entries=(char**)cJSON_malloc(numentries*sizeof(char*));
464     if (!entries) return 0;
465     names=(char**)cJSON_malloc(numentries*sizeof(char*));
466     if (!names) {cJSON_free(entries);return 0;}
467     memset(entries,0,sizeof(char*)*numentries);
468     memset(names,0,sizeof(char*)*numentries);
469 
470     /* Collect all the results into our arrays: */
471     child=item->child;depth++;if (fmt) len+=depth;
472     while (child)
473     {
474         names[i]=str=print_string_ptr(child->string);
475         entries[i++]=ret=print_value(child,depth,fmt);
476         if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
477         child=child->next;
478     }
479     
480     /* Try to allocate the output string */
481     if (!fail) out=(char*)cJSON_malloc(len);
482     if (!out) fail=1;
483 
484     /* Handle failure */
485     if (fail)
486     {
487         for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
488         cJSON_free(names);cJSON_free(entries);
489         return 0;
490     }
491     
492     /* Compose the output: */
493     *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
494     for (i=0;i<numentries;i++)
495     {
496         if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
497         strcpy(ptr,names[i]);ptr+=strlen(names[i]);
498         *ptr++=':';if (fmt) *ptr++='\t';
499         strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
500         if (i!=numentries-1) *ptr++=',';
501         if (fmt) *ptr++='\n';*ptr=0;
502         cJSON_free(names[i]);cJSON_free(entries[i]);
503     }
504     
505     cJSON_free(names);cJSON_free(entries);
506     if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
507     *ptr++='}';*ptr++=0;
508     return out;    
509 }
510 
511 /* Get Array size/item / object item. */
512 int    cJSON_GetArraySize(cJSON *array)                            {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
513 cJSON *cJSON_GetArrayItem(cJSON *array,int item)                {cJSON *c=array->child;  while (c && item>0) item--,c=c->next; return c;}
514 cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)    {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
515 
516 /* Utility for array list handling. */
517 static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
518 /* Utility for handling references. */
519 static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;mymemcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
520 
521 /* Add item to array/object. */
522 void   cJSON_AddItemToArray(cJSON *array, cJSON *item)                        {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
523 void   cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item)    {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
524 void    cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)                        {cJSON_AddItemToArray(array,create_reference(item));}
525 void    cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item)    {cJSON_AddItemToObject(object,string,create_reference(item));}
526 
527 cJSON *cJSON_DetachItemFromArray(cJSON *array,int which)            {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
528     if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
529 void   cJSON_DeleteItemFromArray(cJSON *array,int which)            {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
530 cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
531 void   cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
532 
533 /* Replace array/object items with new ones. */
534 void   cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem)        {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
535     newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
536     if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
537 void   cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
538 
539 /* Create basic types: */
540 cJSON *cJSON_CreateNull(void)                    {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
541 cJSON *cJSON_CreateTrue(void)                    {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
542 cJSON *cJSON_CreateFalse(void)                    {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
543 cJSON *cJSON_CreateBool(int b)                    {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
544 cJSON *cJSON_CreateNumber(double num)            {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
545 cJSON *cJSON_CreateString(const char *string)    {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
546 cJSON *cJSON_CreateArray(void)                    {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
547 cJSON *cJSON_CreateObject(void)                    {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
548 
549 /* Create Arrays: */
550 cJSON *cJSON_CreateIntArray(const int *numbers,int count)        {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
551 cJSON *cJSON_CreateFloatArray(const float *numbers,int count)    {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
552 cJSON *cJSON_CreateDoubleArray(const double *numbers,int count)    {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
553 cJSON *cJSON_CreateStringArray(const char **strings,int count)    {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
554 
555 /* Duplication */
556 cJSON *cJSON_Duplicate(cJSON *item,int recurse)
557 {
558     cJSON *newitem,*cptr,*nptr=0,*newchild;
559     /* Bail on bad ptr */
560     if (!item) return 0;
561     /* Create new item */
562     newitem=cJSON_New_Item();
563     if (!newitem) return 0;
564     /* Copy over all vars */
565     newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
566     if (item->valuestring)    {newitem->valuestring=cJSON_strdup(item->valuestring);    if (!newitem->valuestring)    {cJSON_Delete(newitem);return 0;}}
567     if (item->string)        {newitem->string=cJSON_strdup(item->string);            if (!newitem->string)        {cJSON_Delete(newitem);return 0;}}
568     /* If non-recursive, then we're done! */
569     if (!recurse) return newitem;
570     /* Walk the ->next chain for the child. */
571     cptr=item->child;
572     while (cptr)
573     {
574         newchild=cJSON_Duplicate(cptr,1);        /* Duplicate (with recurse) each item in the ->next chain */
575         if (!newchild) {cJSON_Delete(newitem);return 0;}
576         if (nptr)    {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;}    /* If newitem->child already set, then crosswire ->prev and ->next and move on */
577         else        {newitem->child=newchild;nptr=newchild;}                    /* Set newitem->child and move to it */
578         cptr=cptr->next;
579     }
580     return newitem;
581 }
582 
583 void cJSON_Minify(char *json)
584 {
585     char *into=json;
586     while (*json)
587     {
588         if (*json==' ') json++;
589         else if (*json=='\t') json++;    // Whitespace characters.
590         else if (*json=='\r') json++;
591         else if (*json=='\n') json++;
592         else if (*json=='/' && json[1]=='/')  while (*json && *json!='\n') json++;    // double-slash comments, to end of line.
593         else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;}    // multiline comments.
594         else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive.
595         else *into++=*json++;            // All other characters.
596     }
597     *into=0;    // and null-terminate.
598 }

cJSON.h內容如下
  1 /*
  2   Copyright (c) 2009 Dave Gamble
  3  
  4   Permission is hereby granted, free of charge, to any person obtaining a copy
  5   of this software and associated documentation files (the "Software"), to deal
  6   in the Software without restriction, including without limitation the rights
  7   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8   copies of the Software, and to permit persons to whom the Software is
  9   furnished to do so, subject to the following conditions:
 10  
 11   The above copyright notice and this permission notice shall be included in
 12   all copies or substantial portions of the Software.
 13  
 14   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 15   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 16   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 17   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 18   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 19   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 20   THE SOFTWARE.
 21 */
 22 
 23 #ifndef cJSON__h
 24 #define cJSON__h
 25 
 26 #include <stddef.h>
 27 
 28 #ifdef __cplusplus
 29 extern "C"
 30 {
 31 #endif
 32 
 33 /* cJSON Types: */
 34 #define cJSON_False 0
 35 #define cJSON_True 1
 36 #define cJSON_NULL 2
 37 #define cJSON_Number 3
 38 #define cJSON_String 4
 39 #define cJSON_Array 5
 40 #define cJSON_Object 6
 41     
 42 #define cJSON_IsReference 256
 43 
 44 /* The cJSON structure: */
 45 typedef struct cJSON {
 46     struct cJSON *next,*prev;    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
 47     struct cJSON *child;        /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
 48 
 49     int type;                    /* The type of the item, as above. */
 50 
 51     char *valuestring;            /* The item's string, if type==cJSON_String */
 52     int valueint;                /* The item's number, if type==cJSON_Number */
 53     double valuedouble;            /* The item's number, if type==cJSON_Number */
 54 
 55     char *string;                /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
 56 } cJSON;
 57 
 58 
 59 
 60 typedef struct cJSON_Hooks {
 61       void *(*malloc_fn)(size_t sz);
 62       void (*free_fn)(void *ptr);
 63 } cJSON_Hooks;
 64 
 65 /* Supply malloc, realloc and free functions to cJSON */
 66 extern void cJSON_InitHooks(cJSON_Hooks* hooks);
 67 
 68 
 69 /* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
 70 extern cJSON *cJSON_Parse(const char *value);
 71 /* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
 72 extern char  *cJSON_Print(cJSON *item);
 73 /* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
 74 extern char  *cJSON_PrintUnformatted(cJSON *item);
 75 /* Delete a cJSON entity and all subentities. */
 76 extern void   cJSON_Delete(cJSON *c);
 77 
 78 /* Returns the number of items in an array (or object). */
 79 extern int      cJSON_GetArraySize(cJSON *array);
 80 /* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
 81 extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
 82 /* Get item "string" from object. Case insensitive. */
 83 extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
 84 
 85 /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
 86 extern const char *cJSON_GetErrorPtr(void);
 87     
 88 /* These calls create a cJSON item of the appropriate type. */
 89 extern cJSON *cJSON_CreateNull(void);
 90 extern cJSON *cJSON_CreateTrue(void);
 91 extern cJSON *cJSON_CreateFalse(void);
 92 extern cJSON *cJSON_CreateBool(int b);
 93 extern cJSON *cJSON_CreateNumber(double num);
 94 extern cJSON *cJSON_CreateString(const char *string);
 95 extern cJSON *cJSON_CreateArray(void);
 96 extern cJSON *cJSON_CreateObject(void);
 97 
 98 /* These utilities create an Array of count items. */
 99 extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
100 extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
101 extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
102 extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
103 
104 /* Append item to the specified array/object. */
105 extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
106 extern void    cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
107 /* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
108 extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
109 extern void    cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
110 
111 /* Remove/Detatch items from Arrays/Objects. */
112 extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
113 extern void   cJSON_DeleteItemFromArray(cJSON *array,int which);
114 extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
115 extern void   cJSON_DeleteItemFromObject(cJSON *object,const char *string);
116     
117 /* Update array items. */
118 extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
119 extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
120 
121 /* Duplicate a cJSON item */
122 extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
123 /* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
124 need to be released. With recurse!=0, it will duplicate any children connected to the item.
125 The item->next and ->prev pointers are always zero on return from Duplicate. */
126 
127 /* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
128 extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
129 
130 extern void cJSON_Minify(char *json);
131 
132 /* Macros for creating things quickly. */
133 #define cJSON_AddNullToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateNull())
134 #define cJSON_AddTrueToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
135 #define cJSON_AddFalseToObject(object,name)        cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
136 #define cJSON_AddBoolToObject(object,name,b)    cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
137 #define cJSON_AddNumberToObject(object,name,n)    cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
138 #define cJSON_AddStringToObject(object,name,s)    cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
139 
140 /* When assigning an integer value, it needs to be propagated to valuedouble too. */
141 #define cJSON_SetIntValue(object,val)            ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
142 
143 #ifdef __cplusplus
144 }
145 #endif
146 
147 #endif

 





 

 

下面是JSON數據的解析部分,簡單說來就是對號入座。

  1 /**************************************************************************
  2 函數功能:JSON字符串解析,按照命令格式,解析出上位機發送的命令
  3 入口參數:JSON格式的字符串,
  4 返回  值:指令類型
  5 注    意:從服務器的socket得到的字符串是加密了的字符串,需要首先解密后才能放入此函數
  6 **************************************************************************/
  7 CommandType GetCommandFromServer(char * JsonDataFromSocket)
  8 {
  9     
 10 //  ROBOCmd_TypeDef cmd;//使用的時候用全部結構體代替
 11     
 12 //    Hello_Ack_TypeDef hello_ack;//使用的時候用全局接頭體代替
 13     CommandType cmdtype;
 14   RobotJSON_CMD_TypeDef json_cmd;    
 15     HelloJSON_Ack_TypeDef json_ack;
 16     
 17   cJSON *root,*command_root;
 18 
 19   root =     cJSON_Parse(JsonDataFromSocket); //實例化JSON對象(靜態對象)    
 20     if(!root) 
 21             {
 22                  //printf("get cJSON  faild !\n");
 23                 cmdtype=NOCOMMAND;//如果沒有,就直接返回0
 24              } 
 25             else
 26                 {
 27                  command_root = cJSON_GetObjectItem(root, "RobotCommand"); //取RobotCommand鍵值對
 28                     if(!command_root) 
 29                         { 
 30                                 //printf("No RobotCommand !\n"); 
 31                             
 32                                 command_root = cJSON_GetObjectItem(root, "HelloACK"); //取hellACK鍵值對
 33                                     if(!command_root)
 34                                     {
 35                                          //將函數的返回值改下 既不是RobotCommand也不是HelloACK的情況就返回0
 36                                              cmdtype=NOCOMMAND;//如果沒有,就直接返回0
 37                                     }
 38                                     else{
 39                                                 
 40                                     
 41                                             json_ack.ID = cJSON_GetObjectItem(command_root,"ID");
 42                                             if(!json_ack.ID)
 43                                                 {
 44                                                     cmdtype=NOCOMMAND;//如果沒有,就直接返回0
 45                                                 }
 46                                             else
 47                                                 {
 48                                                          strcpy(Ack_From_Server.ID,json_ack.ID->valuestring);
 49                                                 }
 50                                             json_ack.Time = cJSON_GetObjectItem(command_root,"Time");
 51                                             if(!json_ack.Time)
 52                                                 {
 53                                                     cmdtype=NOCOMMAND;//如果沒有,就直接返回0
 54                                                 }
 55                                             else
 56                                                 {
 57                                                          strcpy(Ack_From_Server.Time,json_ack.Time->valuestring);                    
 58                                                 }
 59 
 60                                                 cmdtype=HELLO_ACK;//如果沒有,就直接返回0
 61                                     }
 62                         }
 63                     else
 64                         {
 65                             
 66                             //運動命令
 67                               json_cmd.Command =cJSON_GetObjectItem(command_root,"Command");
 68                             if(!json_cmd.Command) 
 69                                 { 
 70                                     //printf("no Command!\n");
 71                                         //cmdtype=NOCOMMAND;//如果沒有,就直接返回0    
 72                                 } 
 73                             else
 74                                 {
 75                                                 //printf("Command is %s\r\n", robocmd.Command->valuestring);
 76                                                  strcpy(Cmd_From_Server.Command,json_cmd.Command->valuestring);
 77                                     //此時應該發送對應命令的OK程序,Set或者Auto或者。。。具體見協議
 78                                     
 79                                 }
 80                             //速度指令
 81                             json_cmd.Speed=cJSON_GetObjectItem(command_root,"Speed");
 82                             if(!json_cmd.Speed) 
 83                                 { 
 84                                     //printf("no Speed!\n");     
 85 //                                    cmdtype=NOCOMMAND;//如果沒有,就直接返回0
 86                                 } 
 87                             else
 88                                 {
 89                                                 //printf("Speed is %d\r\n", json_cmd.Speed->valueint);
 90                                                 Cmd_From_Server.Speed=json_cmd.Speed->valueint;
 91                                 }
 92                             
 93                                 //運行次數
 94                                 json_cmd.RunCount = cJSON_GetObjectItem(command_root,"RunCount");
 95                             if(!json_cmd.RunCount) 
 96                                 { 
 97                                     //printf("no RunCount!\n"); 
 98 //                                        cmdtype=NOCOMMAND;//如果沒有,就直接返回0
 99                                 } 
100                             else
101                                 {
102                                             //printf("RunCount is %d\r\n",json_cmd.RunCount->valueint);
103                                             Cmd_From_Server.RunCount=json_cmd.RunCount->valueint;
104                                 }
105                                 //開始位置
106                                     json_cmd.StartPosition = cJSON_GetObjectItem(command_root,"StartPosition");
107                             if(!json_cmd.StartPosition) 
108                                 { 
109                                     //printf("no StartPosition!\n"); 
110 //                                        cmdtype=NOCOMMAND;//如果沒有,就直接返回0
111                                 } 
112                             else
113                                 {
114                                             //printf("StartPosition is %d\r\n",json_cmd.StartPosition->valueint);
115                                             Cmd_From_Server.StartPosition=json_cmd.StartPosition->valueint;
116                                 }
117                                 //結束位置
118                                             json_cmd.EndPosition = cJSON_GetObjectItem(command_root,"EndPosition");
119                             if(!json_cmd.EndPosition) 
120                                 { 
121                                     //printf("no EndPosition!\n"); 
122 //                                        cmdtype=NOCOMMAND;//如果沒有,就直接返回0
123                                 } 
124                             else
125                                 {
126                                             //printf("EndPosition is %d\r\n",json_cmd.EndPosition->valueint);
127                                             Cmd_From_Server.EndPosition=json_cmd.EndPosition->valueint;
128                                 }
129                                 //目標位置TargetPosition
130                                                         json_cmd.TargetPosition = cJSON_GetObjectItem(command_root,"TargetPosition");
131                             if(!json_cmd.TargetPosition) 
132                                 { 
133                                     //printf("no TargetPosition!\n"); 
134 //                                        cmdtype=NOCOMMAND;//如果沒有,就直接返回0
135                                 } 
136                             else
137                                 {
138                                             //printf("TargetPosition is %d\r\n",json_cmd.TargetPosition->valueint);
139                                             Cmd_From_Server.TargetPosition=json_cmd.TargetPosition->valueint;
140                                 }
141                             
142                                 //*工作模式WorkMode;
143                                  json_cmd.WorkMode= cJSON_GetObjectItem(command_root,"WorkMode");
144                                 if(!json_cmd.WorkMode) 
145                                 { 
146                                     //printf("no WorkMode!\n"); 
147 //                                        cmdtype=NOCOMMAND;//如果沒有,就直接返回0
148                                 } 
149                             else
150                                 {
151                                             //printf("WorkMode is %s\r\n",json_cmd.WorkMode->valuestring);
152                                              strcpy(Cmd_From_Server.WorkMode,json_cmd.WorkMode->valuestring);
153                                 }
154                                 //step
155                                      json_cmd.Step= cJSON_GetObjectItem(command_root,"Step");
156                                 if(!json_cmd.Step) 
157                                 { 
158                                     //printf("no Step!\n"); 
159 //                                        cmdtype=NOCOMMAND;//如果沒有,就直接返回0
160                                 } 
161                             else
162                                 {
163                                             //printf("Step is %d\r\n",json_cmd.Step->valueint);
164                                             Cmd_From_Server.Step=json_cmd.Step->valueint;
165                                 }
166                                 
167                                 
168                                 cmdtype= COMMAND;
169                                 
170                         } 
171              }
172 
173 cJSON_Delete(root);
174 
175 return cmdtype;
176 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM