Json和cJson的學習總結以及在STM32裏移植cJSON需要注意哪些問題

最近在做項目的時候遇到了JSON格式的數據。需要對Json格式的數據進行解析,而我所使用的設備是嵌入式單片機,因此需要藉助cJson來將Json和C語言結合起來。這篇文章就是我對Json和cJson相關內容知識的一個總結。

1 JSON的介紹

1.1 JSON產生的原因

首先,JSON爲什麼出現。Json是一種人們規定的數據交換格式。在現實生活中,我們需要進行數據交換的情景非常多,但是許多情況下,由於各個設備所採用的語言、架構不同,因此一個設備內部的數據、變量、結構體、對象等不能被其他設備所識別,這就好像一箇中國人需要的數字格式是一、二、三,一個英國人需要的數字格式是one、two、three,這兩個人是無法進行正常的數據交換的。
那麼這個時候如果我們把我們所需要交換的數據,通過某種固定的格式,變成大家都能識別的語言,這樣的話,數據的交換隻交換大家都能識別的語言,每個設備就不需要考慮數據交換的對方的語言,而只需要對要交換的數據按照約定的格式進行打包和解析。就像中國人和英國人只需要各自將數字轉化爲1、2、3的格式,或者將1、2、3格式的數字轉化爲各自所需要的語言格式,這樣兩個人就能正常交流了。

1.2 JSON的格式

那麼我們已經知道了Json產生的原因,那麼一個Json具體是什麼樣的呢?網上很多文章都提到了JSON的鍵、鍵值、數組等等,這樣看起來JSON也很複雜,難以理解。其實我們抓住本質來說,JSON首先是一個純的文本(字符串)。因爲JSON是需要在各個編程語言中都能存在的,因此JSON的本質就是一堆文本。只不過因爲這種文本爲了方便打包和解析,我們定義了具體的寫法和結構,因此我們可以給出定義:用於數據交換的、採用這種寫法的、字符串、就叫JSON。

那麼具體來說JSON是採用怎樣的寫法呢?也就是說,JSON的結構是什麼。要弄清楚這個,首先我們要有一定的編程基礎,知道在我們常用的語言中,例如C、C++、Java等,變量的種類都有什麼。因爲JSON的目的是將一個設備中的變量告訴給另個一設備,所以首先我們要知道我們需要在JSON中表達出來的變量的類型都有什麼。然後當我們知道了我們需要表達的類型,我們再去知道通過什麼樣的格式來將變量構造成文本。

那麼在常用的語言中,變量的種類基本上可以分爲兩種(這裏我們不是討論變量的具體形式例如整形、浮點型,而是談論變量的表達方法),一種是對象,一種是數組。一個對象具有屬性,每個屬性又有該屬性的屬性值。例如某同學是一個對象,該同學具有的屬性有姓名,年齡等,每個屬性有其對應的屬性值,“小明”、“15”,屬性值可以是數值、字符串、數組、對象等形式。
那麼我們如何把上述的對象轉化爲JSON格式的文本呢?

//實際交換時的JSON數據
{"student": { "name": "小明","age":15}}


//便於閱讀的JSON數據
{
    "student": 
        {
            "name": "小明",
            "age":15
        }
}

入上圖所示,“student”:表示對象,{ }表示對象的內容,對象內容裏
"name"表示屬性,“:”後面跟的是屬性值,“,”表示並列的屬性。通過這樣的文本我們就將一個對象轉化爲了JSON數據,從而能夠進行數據交換。

之前我們介紹到,數據的類型還有數組的形式,同樣舉例來說,加入我們現在面向整個班級,每個班級的學生都是一個對象,這麼多個對象在一起組成一數組,這個數組就是我們所說的班級,那麼如何把一個班的數據轉化爲JSON格式呢?

//實際交換時的JSON數據
{"class":{"class_number":1,"students":[{"name": "小明","age":15},{"name": "小紅","age":14}, {"name": "小強","age":14}]}}


//便於閱讀的JSON數據
{
    "class":
        {
            "class_number":1,
            "students":[
                {
                    "name": "小明",
                    "age":15
                },
                {
                    "name": "小紅",
                    "age":14
                },      
                {
                    "name": "小強",
                    "age":14
                }]        
      }
  }

這裏通過“[ ]”來表達數組。

總結來說,
1.首先一個JSON格式的文本以“{ }”爲開頭和結尾。
2.“{ }”內的爲該對象所包含的屬性。
3.屬性加“ : ”的後面是該屬性的屬性值。
4.“,”表示相同對象中的不同屬性,或相同數組裏的不同個體。
5.“[ ]”表示數組。
6.數組和對象的區別在於,數組的成員是具有屬性的不同個體,而對象的成員的是不同屬性。

通過這種文本架構,我們就能將許多變量轉化爲我們所需要的JSON格式來進行數據交換。

到這裏我們已經基本上對於JSON有了一個瞭解。此外補充幾點,因爲JSON的這種格式其實是在javascript中延伸出來的,可以存儲Javascript複合對象,因此在這類平臺中使用較爲方便。

這裏介紹一個網站可以進行JSON的數據在線解析。
https://www.json.cn/

以及JSON的說明網站
http://www.json.org/

2 cJSON的介紹

2.1 什麼是cJSON,什麼是cJSON結構體

接下來我們來將目光轉向cJson。

Json在C語言中的使用存在一個問題,那就是C語言是一種面向過程的語言,和其他語言不同,因此C語言中沒有對象等定義。那麼Json在C語言的平臺的使用過程中,就需要進行一些獨屬於C語言的解析和打包方法,這種基於C語言的JSON的處理方法我們稱之爲cJson。

目前已經有別人寫好的cJSON的開源代碼供我們使用,這樣我們就不用花時間在造輪子上,而只需要學會如何取使用。因此接下來我們重點介紹cJSON的使用。

首先我們要在工程裏包括cJson.c和cJson.h文件。這兩個文件可以在網上自己找。或者我的下載裏也有。

然後我們先從cJson結構體來入手,瞭解如何用C語言打包一個Json和如何用C語言解析一個Json。

上文所說。C語言沒有對象這一概念,因此我們定義了一個結構體,我們稱這個結構體爲cJson結構體,從而將對象轉化爲了CJSON格式的結構體。從而在C語言中,我們打包或者解析一個JSON,經歷的步驟爲:需要打包的變量<——>cJson結構體<——>Json文本

從.h文件我們可以找到一個cJson結構體的形式:

typedef struct cJSON {
	struct cJSON *next,*prev;	/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
	struct cJSON *child;		/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */

	int type;					/* The type of the item, as above. */

	char *valuestring;			/* The item's string, if type==cJSON_String */
	int valueint;				/* The item's number, if type==cJSON_Number */
	double valuedouble;			/* The item's number, if type==cJSON_Number */

	char *string;				/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;

這裏一個cjson結構體包含變量有:

struct cJSON *next,*prev;  //指向上一個/下一個cJSON的指針,用於鏈表結構
struct cJSON *child;       //指向該cJson的子對象的cJson指針
int type;                   //該cJson結構體所包含的項目的類型
char *valuestring;			//這個項目的值:字符串。如果type=cJSON_String
int valueint;				//這個項目的值:int數字。如果type=cJSON_Number
double valuedouble;			//這個項目的值:double數字,如果type=cJSON_Number
char *string;	            //該項目的名稱(字符串),如果該項目在對象的子項列表中或爲對象的子項

那麼還是以上文爲例,如何把上述的JSON文本:

{
    "student": 
        {
            "name": "小明",
            "age":15
        }
}

轉換成cJSON的結構體?
答案就是,首先把總的JSON作爲一個結構體,假設總的cJSON名字爲cJSON_0,那麼cJSON_0的成員爲:

cJSON_0     
{
next=0      //因爲沒有數組類的結構,所以向前向後指針都爲0
prev=0      //因爲沒有數組類的結構,所以向前向後指針都爲0
child=(某地址,指向該cJSON的子系,假設這個子系cJSON爲cJSON_0_0)
type=cJSON_Object    //表明這個cJSON表示的是一個具有內部屬性的對象
valuestring=0
valueint=0	
valuedouble=0
string=0
}
//總的cJSON結構體種類爲cJSON_Object,表明該結構體代表的是一個JSON對象

然後我們打開這個cJSON_0的子系所指的結構體,發現該結構體的成員爲:

cJSON_0_0     
{
next=0       //因爲沒有數組類的結構,所以向前向後指針都爲0
prev=0      //因爲沒有數組類的結構,所以向前向後指針都爲0
child=(某地址,指向該cJSON的子系,假設這個子系cJSON爲cJSON_0_0_0)
type=cJSON_Object    //表明這個cJSON表示的是一個具有內部屬性的對象
valuestring=0
valueint=0	
valuedouble=0
string="student"    //該項目名爲“student”
}
//該cJSON表示的是“student”這個項目,項目類型爲cJSON_Object,因爲該項目是一個對象,這個對象還有其內在的屬性

然後再打開該cJSON的子系,即cJSON_0_0_0,其成員爲

cJSON_0_0_0     
{
next=(下一個同級的cJSON結構體,假設爲cJSON_0_0_1 )       //因爲這裏是有和“name”項目同級的“age”存在
prev=0      //因爲沒有數組類的結構,所以向前向後指針都爲0
child=0      //因爲這個是最內層的項目,沒有子項目了,所以無子系,子系的指針爲0
type=cJSON_String    //表明該cJSON表示的是一個字符串
valuestring="小明"      //字符串的值
valueint=0	  
valuedouble=0
string="name"         //表明該項目的名稱爲“name”
}
//該cJSON表示的是“student”這個項目,項目類型爲cJSON_Object,因爲該項目是一個對象,這個對象還有其內在的屬性

以及next指針指向的下一個cJOSN結構體cJSON_0_0_1:

cJSON_0_0_1     
{
next=0       //因爲這個是該層的最後一個
prev=(指向cJSON_0_0_0)     //指向上一個同級的cJSON結構體
child=0      //因爲這個是最內層的項目,沒有子項目了,所以無子系,子系的指針爲0
type=cJSON_Number    //表明該cJSON表示的是一個數
valuestring=0     
valueint=0x0F         //表示15	  
valuedouble=15.0      //表示15
string="age"         //表明該項目的名稱爲“age”
}
//該cJSON表示的是“student”這個項目,項目類型爲cJSON_Object,因爲該項目是一個對象,這個對象還有其內在的屬性

通過這種cJSON結構體,就把JSON文本中的各個項目嵌套的關係表現了出來。即

{
    "student": 
        {
            "name": "小明",
            "age":15
        }
}

將上述JSON轉化爲了具有父子關係和同輩關係的總共四個cJSON結構體

cJSON_0     :總的JSON項目,類型爲Object,包含cJSON_0_0
cJSON_0_0   :項目名“student”,類型爲Object,包含cJSON_0_0_0
cJSON_0_0_0 :項目名“name”,類型爲String,值爲“小明”,有下一個cJSON指針cJSON_0_0_1
cJSON_0_0_1 :項目名“age”,類型爲Number,值爲15,有上一個cJSON指針cJSON_0_0_0

以上的所有數值都是經過了debug驗證過的。

2.2 如何將JSON文本轉化爲cJSON結構體之間的相互轉化

接下來我們將介紹在cJSON.c中,如何實現JSON和cJSON之間的相互轉化。

這裏用到了cJSON的兩個比較重要的函數分別是:

extern cJSON *cJSON_Parse(const char *value);     
//函數名:cJSON_Parse()
//功能:cJSON解析函數,將JSON轉化爲cJSON結構體
//輸入:JSON文本的指針
//返回值:最外層的cJSON結構體的指針
//注意事項:當cJSON使用完成後,需要手動調用cJSON_Delete()函數來釋放內存

以及

extern char  *cJSON_Print(cJSON *item);
//函數名:cJSON_Print()
//功能:cJSON打包函數,將cJSON結構體轉化爲JSON文本
//輸入:最外層的cJSON結構體的指針
//返回值:轉化後的JSON文本的指針
//注意事項:當JSON文本發送完成後,需要手動free掉JSON文本所佔用的內存

此外,我們還可能用到一些輔助上述兩個函數的其他函數,例如:

extern void   cJSON_Delete(cJSON *c); 
//函數名:cJSON_Delete()
//功能:刪除cJSON結構體
//輸入:最外層的cJSON結構體的指針
//返回值:無

以及

extern const char *cJSON_GetErrorPtr(void);
//函數名:cJSON_GetErrorPtr()
//功能:當cJSON解析出錯時,獲得解析失敗處的字符的指針
//輸入:無
//返回值:解析失敗處的字符的指針

相應的解析和打包的代碼如下:


cJSON* A;  //定義一個cJSON結構體變量 A
char*  B;    //定義一個字符串 B
char*  C="{"student": { "name": "小明","age":15}}";    //定義一個字符串 C,假設C就是我們所接收到的JSON

A=cJSON_Parse(C);        //把C解析成cJSON結構體,幅值給A
if(A == NULL )                 //A=NULL表明解析失敗
{
  printf("Error before: [%s]\n",cJSON_GetErrorPtr());    //從解析失敗處開始將剩下的字符打印出
}
else                               //解析成功,A爲cJSON結構體
{
  B=cJSON_Print(A);          //把A的cJSON結構體打包成JSON字符串
  if(B == NULL)                  //打包失敗
  {
    u2_printf("CJSON Print error");  //打印"CJSON Print error"
  }
  else	u2_printf("%s /r/n",B);    //解析成功,將打包後的JSON字符串打印出來
}
cJSON_Delete(A);                     //刪除cJSON結構體
free(B);                                     //釋放B所佔的內存


此外,補充一點,上述的打包和解析對於數組也是一樣的,只是數組對應的cJSON裏的type爲cJSON_Array。

2.3 如何提取cJSON結構體中的變量

到這裏,我們已經知道了如何把JSON解析爲cJSON結構體。距離我們上文所說的:需要打包的變量<——>cJson結構體<——>Json文本,就還差 “ 變量<——>cJson結構體 ” 需要完成。這裏就是涉及到我們的具體使用情景了。這裏爲了敘述方便,我們把從cJSON結構體到具體變量叫做提取,把從具體變量到cJSON叫做構成。

首先我們先將,如何從cJSON結構體中提取我們所想要的某個項目的項目值。(這裏我們是在已知JSON格式,但是其中的屬性值未知的的情況下談論這些事情的)

這裏也是用到了幾個庫函數,如下所示:

extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); 
//函數名:cJSON_GetObjectItem();
//作用:在大一層的cJSON結構體中,根據給定的項目名,得到該項目名的cJSON結構體
//輸入:cJSON* object,數據類型爲cJSON_Object的cJSON結構體
//          char * string,我們所需要的項目的項目名
//輸出:我們所要求的項目的cJSON結構體的指針
//          如果想要提取該項目的項目值,可以利用結構體的格式"->"來取到結構體內部的值,具體的使用方法我們下面會有實例講解
//這裏應該注意的地方是,該函數只能對包含該項目名的最小的那個cJSON_Object進行提取。假如說從一個大的cJSON中找到我們所需要的那一項,這個過程就像剝洋蔥一樣一層cJSON一層cJSON的提取,那麼這個cJSON_GetObjectItem()函數一次調用只能夠剝一層皮。

然後是當我們需要提取數組類型的cJSON時,需要用到以下兩個函數:

extern int	  cJSON_GetArraySize(cJSON *array);
//函數名:cJSON_GetArraySize()
//功能:得到cJSON數組中的成員的個數
//輸入:cJSON *array ,數據類型爲cJSON_Array的cJSON結構體
//返回值:數組內的成員個數
//這裏需要注意的是,輸入的數組一定要是一個cJSON_Array型的cJSON結構體

以及

extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); 
//函數名:cJSON_GetArrayItem()
//功能:根據下標獲得cJSON數組中的成員的指針
//輸入:cJSON *array ,數據類型爲cJSON_Array的cJSON結構體
//           int item,成員的下標,從0到size-1共size個成員
//返回值:某下標的成員的cJSON結構體指針
//這裏需要注意的是,輸入的數組一定要是一個cJSON_Array型的cJSON結構體

對於上述三個函數的應用,我們也是通過一個實例來表現:

cJSON* A;  //定義一個cJSON結構體變量 A
cJSON* AA; //定義一個cJSON結構體變量,該變量用於表達A的子系
cJSON* AAA; //定義一個cJSON結構體變量,該變量用於表達AA的子系
cJSON* AAAA; //定義一個cJSON結構體變量,該變量用於表達AAA的子系
cJSON* NAME;   //item名爲name的cJSON    
cJSON* AGE;     //item名爲age的cJSON    
char*  name;    
u8     age;
u8     n,i;

char*  C="{"class":{"class_number":1,"students":[{"name": "小明","age":15},{"name": "小紅","age":14}, {"name": "小強","age":14}]}}";    //定義一個帶有數組的字符串 C,假設C就是我們所接收到的JSON
     
            A=cJSON_Parse(C);
			if(A == NULL )
			{
				printf("Error Parse before: [%s]\n",cJSON_GetErrorPtr());
			}
			else 
			{
				AA=(cJSON_GetObjectItem(A,"class"));
				AAA=(cJSON_GetObjectItem(AA,"students"));
				n=cJSON_GetArraySize(AAA);                  //獲得數組成員個數
				u2_printf("arr_num=%u \r\n",n);
				delay_ms(50);
				for(i=0;i<n;i++)                     //從成員0到成員2,依次打印
				{
					AAAA=cJSON_GetArrayItem(AAA,i);      //成員1的cJOSN_Object
					NAME=(cJSON_GetObjectItem(AAAA,"name"));
					if(NAME==NULL)	u2_printf("ERROR NAME \r\n");
					else
					{
						name=NAME->valuestring;
						u2_printf("student%u_name=%s \r\n",i,name);
					}
					delay_ms(50);
					AGE=cJSON_GetObjectItem(AAAA,"age");
					if(AGE==NULL) u2_printf("ERROR AGE \r\n");
					else
					{
						age=AGE->valueint;
						u2_printf("student%u_age=%u \r\n",i,age);
					}
					delay_ms(50);
				}
cJSON_Delete(A);                     //刪除cJSON結構體

打印結果如下所示:
在這裏插入圖片描述

通過上面三個函數,我們就能夠將已經解析好的cJSON的信息提取出來,得到其各個項目的屬性值。這樣就完成了提取這一操作,從而將cJSON轉化爲了變量。

2.4 如何將變量構成爲cJSON結構體

接下來我們需要談論的就是,如何將變量組合成cJSON的結構體。如果我們要把某些變量作爲JSON文本發出去,我們的步驟是,先將我們要發的所有變量組合成cJSON結構體的格式,然後我們在通過上述的cjson_print,將cJSON結構體轉化爲了JSON文本併發送。後面這一步。

這裏也是主要用一些庫函數來實現。下面也是先介紹庫函數,然後再通過一個實例來實現cJSON結構體的構造。

首先是構造cJSON結構體常用的庫函數:

首先是創造cJSON結構體函數,它根據所創造的cJSON結構體的類型不同,而採用不同的函數,這裏我們就不一一介紹這些函數。

/* These calls create a cJSON item of the appropriate type. */
extern cJSON *cJSON_CreateNull(void);
extern cJSON *cJSON_CreateTrue(void);
extern cJSON *cJSON_CreateFalse(void);
extern cJSON *cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateString(const char *string);
extern cJSON *cJSON_CreateArray(void);
extern cJSON *cJSON_CreateObject(void);

//cJSON_CreateNull();  創造NULL類型的cJSON結構體,不需要輸入值
//cJSON_CreateTrue();  創造TRUE類型的cJSON結構體,不需要輸入值
//cJSON_CreateFalse();  創造FALSE類型的cJSON結構體,不需要輸入值
//cJSON_CreateBool();  創造BOOL類型的cJSON結構體,輸入值爲1或0
//cJSON_CreateNumber();  創造NUMBER類型的cJSON結構體,輸入值爲double
//cJSON_CreateString();  創造STRING類型的cJSON結構體,輸入值爲字符串指針
//cJSON_CreateString();  創造ARRAY類型的cJSON結構體,不需要輸入值
//cJSON_CreateString();  創造ARRAY類型的cJSON結構體,不需要輸入值

//這裏cJSON_CreateString()和cJSON_CreateString()不需要輸入值,但是需要採用其他函數來對成員進行添加。

//上述所有的函數輸出爲我們所創造得到的cJSON的結構體的指針

此外在進行數組創造的時候,也可以直接將我們需要組合的item直接生成爲一個ARRAY類型的cJSON結構體。主要是以下幾個函數:

/* These utilities create an Array of count items. */   
extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);

//cJSON_CreateIntArray();創造一個成員爲int型的array型cJSON

以及向現有的Object/Arrary裏添加其他item。

/* Append item to the specified array/object. */          
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
extern void	cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
extern void	cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item);
	/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */


//cJSON_AddItemToArray();         //在一個Array型的cJSON裏添加cJSON成員
//cJSON_AddItemToObject();       //在一個Object型的cJSON裏添加cJSON成員,這裏輸入值string爲要添加的cJSON的鍵值
//cJSON_AddItemToObjectCS();  //在一個Object型的cJSON裏添加cJSON成員,這裏輸入值string爲要添加的cJSON的鍵值,且該鍵值是一個const string,所以在cjson_delet();執行的時候,會跳過刪除該字符串。


//此外還有帶有引用性質的構成函數
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
extern void	cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);

//cJSON_AddItemReferenceToArray();         //用一個item來引用一個array型cJSON,在刪除該item時,不會刪除其引用的array型cJSON
//cJSON_AddItemToObject();       //用一個item來引用一個object型cJSON,在刪除該item時,不會刪除其引用的object型cJSON

以及從cJSON結構體裏刪除指定的item

/* Remove/Detatch items from Arrays/Objects. */      
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
extern void   cJSON_DeleteItemFromArray(cJSON *array,int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
extern void   cJSON_DeleteItemFromObject(cJSON *object,const char *string);

/cJSON_DetachItemFromArray();  從array的cJSON結構體中將指定下標的成員分離出來。返回的是分離出來的成員的cJSON指針。爲避免內存泄漏,確保將返回值賦值給一個指針
//cJSON_DeleteItemFromArray();  從array的cJSON結構體中將指定下標的成員刪除。
//cJSON_DetachItemFromObject();  從object的cJSON結構體中將指定下標的成員分離出來。返回的是分離出來的成員的cJSON指針。爲避免內存泄漏,確保將返回值賦值給一個指針
//cJSON_DeleteItemFromObject();  從object的cJSON結構體中將指定下標的成員刪除。

以及提供了可以將cJSON中的成員替換或增加其他cJSON結構體的函數:

extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem);

//cJSON_ReplaceItemInArray();    根據下標替換數組類型的cJSON的成員
//cJSON_ReplaceItemInArray();    根據鍵名替換OBJECT類型的cJSON的成員
//cJSON_InsertItemInArray();        可以將一個新元素插入數組中的某下標的位置,原來位置的成員的下標依次向下順移

如何構成一個較大的cJSON結構體,還是以我們之前的內容爲例:

//假設我們要的cJSON結構體是
{
    "student": 
        {
            "name": "小明",
            "age":15
        }
}
那麼我們的代碼如下:

cJSON *  	A=cJSON_CreateObject();
cJSON *  	AA=cJSON_CreateObject();
char*       out;


cJSON_AddItemToObject(AA, "name", cJSON_CreateString("小明"));
cJSON_AddItemToObject(AA, "age", cJSON_CreateNumber(15));
cJSON_AddItemToObject(A, "student", AA);

out=cJSON_Print(A);
printf("%s \r\n",out);



//假設我們要的cJSON結構體爲數組形式的:
{
    "class":
        {
            "class_number":1,
            "students":[
                {
                    "name": "小明",
                    "age":15
                },
                {
                    "name": "小紅",
                    "age":14
                },      
                {
                    "name": "小強",
                    "age":16
                }]        
      }
  }
//那麼我們的代碼爲

cJSON *  	A=cJSON_CreateObject();
cJSON *  	AA=cJSON_CreateObject();
cJSON *  	AAA=cJSON_CreateArray();
cJSON *  	STUDENT1=cJSON_CreateObject();
cJSON *  	STUDENT2=cJSON_CreateObject();
cJSON *  	STUDENT3=cJSON_CreateObject();
char*       out;

cJSON_AddItemToObject(STUDENT1, "name", cJSON_CreateString("小明"));
cJSON_AddItemToObject(STUDENT1, "age", cJSON_CreateNumber(15));
cJSON_AddItemToObject(STUDENT2, "name", cJSON_CreateString("小紅"));
cJSON_AddItemToObject(STUDENT2, "age", cJSON_CreateNumber(14));
cJSON_AddItemToObject(STUDENT3, "name", cJSON_CreateString("小強"));
cJSON_AddItemToObject(STUDENT3, "age", cJSON_CreateNumber(16));
cJSON_AddItemToArray(AAA,STUDENT1);
cJSON_AddItemToArray(AAA,STUDENT2);
cJSON_AddItemToArray(AAA,STUDENT3);
cJSON_AddItemToObject(AA, "class_number", cJSON_CreateNumber(1));
cJSON_AddItemToObject(AA, "students", AAA);
cJSON_AddItemToObject(A, "class", AA);

out=cJSON_Print(A);
printf("%s \r\n",out);

至此我們的解析基本上告一段落,下面是我在進行STM32移植cJSON時遇到的一些具體的問題和解決方法:

3 在STM32裏移植cJSON遇到的問題和解決方法

1.cJSON_Parse();函數的返回值一直是0
原因,可能是因爲接收到的文本不是標準的JSON格式。建議可以在後面加一個判斷,判斷返回值是否爲NULL,如果是,調用cJSON_GetErrorPtr();函數來獲知在哪裏運行出錯。如果不是,表明對JSON的解析完成。

2.cJSON_Print();函數的返回值一直是0
原因,可能是因爲malloc不成功的原因。也就是給cJSON分配的內存較小。在STM32裏,如果不是用自己編寫的malloc函數,而是用的通用的malloc函數,那麼需要在keil的Option->Target界面把“Use MiceoLIB”勾選。即使用微函數。
在這裏插入圖片描述
並且加入Print函數對於個數較小的JSON能夠打印,但是對於個數較多的JSON不能打印,則還需要在文件中尋找Heap_Size變量,然後將後面的數字改大一些,以給cJSON分配更多的內存。
如下:
在這裏插入圖片描述

3.cJSON_GetObjectItem();函數的返回值爲0
原因:返回值爲0表明沒有找到該鍵名對應的cJSON結構體。因爲cJSON_GetObjectItem()只能對get到object的子系,不能get到object的子系的子系。也就是上文我們所說的,剝洋蔥只能剝一層這個概念。所以注意是不是所寫的鍵名是更內層的cJSON。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章