初識cJSON

先把 cJSON的結構體定義po上來:
cJSON結構體
先講怎麼用,再講每一步操作的作用,最後有可能的話再講原理。

直接先po個簡單示例,看看我們如何通過cJSON來解析一個JSON數據。
cJSON解析實例
先試着能不能看懂(估計是看不懂了),算了算了,直接看看不懂,先來講點“前言”。
.
.
.
.
我們先來講講幾個用到的函數。
首先是 **cJSON cJSON_Parse(const char value);
可以看見,函數的返回類型是一個cJSON指針。函數的傳入參數是一個字符指針。該函數的作用是將json格式的字符串轉換成json對象。具體爲:將一個JSON數據包(即傳入的字符指針所指向地址存放的數據),按照cJSON結構體的結構把整個數據包序列化,並在堆中開闢一塊內存來存儲cJSON結構體(這個作用解釋得跟沒解釋差不多hhh,先簡單理解成初始化一段JSON數據包),而如果傳入該函數的(也就是該char指針所指向的字符串)不是一段JSON格式的數據,則函數返回NULL指針。如果傳入的是JSON數據包,且“初始化”成功,則函數返回一個指向內存塊中的cJSON的指針(也就是返回一個cJSON指針,該指針指向該JSON數據包)。
舉個例子:

char example[] ={\“name\”:\”How\”,\”age\”:18};	//一個存儲json數據包的字符串
cJSON * json;	//創建一個名爲json的cJSON指針
json = cJSON_Parse(example);	//判斷example是否爲JSON數據包
//如果是,則序列化example,然後返回一個cJSON指針
//將返回的指針賦給json變量,即,json指針變量現在指向example這個JSON數據包

.

再來看看 **cJSON *cJSON_GetObjectItem(cJSON object,const char string);
同樣的,函數的返回類型是一個cJSON指針。函數的傳入參數是一個cJSON指針,和一個字符指針。該函數的作用是,獲取JSON數據包中某字符串所對應的字段值,並返回一個指向JSON的cJSON指針。這麼說可能不好理解,我們還是來舉個例子:

char example[] ={\“name\”:\”How\”,\”age\”:18};
cJSON * json;
cJSON * json_age;//這裏我們新建一個名爲json_age的cJSON指針
json = cJSON_Parse(example);
json_age = cJSON_GetObjectItem(json, "age");//這句代碼的作用是:
//向函數提供一個指向JSON數據包的cJSON指針,即json
//以及提供一個該JSON數據包中的某個key的變量名
//那麼函數就會返回一個指向該key變量的值value的cJSON指針
//將返回的指針賦給json_age,於是json_age現在指向age的值
//這樣的話,我們就可以通過json_age來訪問並打印該值了,如:
if( json_age -> type == cJSON_Number )	//判斷age的值是否爲數字
{
	printf("age: %d\n", json_age->valueint);	//若是,以訪問成員變量的方式打印
}

(這個時候再回頭看看cJSON結構體的定義,裏面就有type和valueint,即是cJSON的屬性之一)
.
.
再來看看 **char cJSON_Print(cJSON item);
返回類型是一個字符指針。傳入參數是一個cJSON指針。該函數的作用是,從傳入指針所指的cJSON數據中提取JSON對象的數據,並在堆中開闢一塊char*的內存空間存儲JSON字符串。即從cJSON對象中獲取有格式的JSON對象。(cJSON結構體中不但包含JSON結構的數據——key和value,還包含了其它一些屬性作爲成員變量——如type,valueint)所以通過cJSON_Print函數就能把cJSON中的JSON數據提取出來,並返回給一個字符指針。
還是來舉個例子:

char example[] ={\“name\”:\”How\”,\”age\”:18};
cJSON * json;
char * output;
json = cJSON_Parse(example);
output = cJSON_Print(json);
printf("%s\r\n",output);

這樣就把example解析成JSON字符串並輸出了。但是有人就會問了,這不是瞎折騰嗎?example不是本來就是JSON數據格式的嗎?(%@¥&@%63¥emmm我也不知道…)
.
.
再來看看 *void cJSON_Delete(cJSON c);
這個很好理解,其作用就是釋放cJSON指針佔用的內存。
舉例比如cJSON_Delete(json); cJSON_Delete(json_age);
.
.
.
.
好了,有了以上的瞭解,我們再回過頭來看文章一開頭的代碼:

#include <stdio.h>
#include <stdlib.h>
#include "cjson/cJSON.h"

//新建一個名爲text的json格式的字符串
char text[] = "{\"timestamp\":\"2019-03-03 08:45:57\", \"value\":1}";

void main(int argc, const char *argv[])
{
    cJSON *json, *json_value, *json_timestamp;	//三個cJSON指針變量
    json = cJSON_Parse(text);	//將text字符串轉換成cJSON對象
    if(NULL == json)	//如果text不是json格式
    {
        printf("Error before: [%s]\n", cJSON_GetErrorPtr());
        return -1;
	}
	
	//用json_value指針指向json變量所指的cJSON對象中value的值
    json_value = cJSON_GetObjectItem(json, "value");
    if(json_value->type == cJSON_Number)		//如果該值符合我們所想
    {
        printf("value: %d\n", json_value->valueint);
	}
	
	//同理
    json_timestamp = cJSON_GetObjectItem(json, "timestamp");
    if(json_timestamp->type == cJSON_String)
    {
        printf("%s\n", json_timestamp->valuestring);
	}
	
	//釋放json這個cJSON變量所佔用的內存
    cJSON_Delete(json);
}

以上,我們就實現了JSON字符串的解析,其目的就是使之成爲一個對象,讓我們能夠去訪問該字符串裏面的各種數據。

那麼,前面我們是通過已有JSON字符串來解析成對象,那麼我們能不能反過來,自己創建一個JSON對象呢?答案當然是可以的。能力有限,不解釋,直接po代碼了:

#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"

void main(void)
{
	cJSON * student_json;	//學生信息
	cJSON * grades_json;	//成績信息
	char * output = NULL;	//用於輸出json字符串
	
	/////////////////////////////////////////////////////////////////////////////////////
	student_json = cJSON_CreateObject();
	grades_json = cJSON_CreateObject();
	
	cJSON_AddItemToObject(student_json, "name", cJSON_CreateString("陳how"));
	cJSON_AddItemToObject(student_json, "qq", cJSON_CreateNumber(772541523));
	cJSON_AddItemToObject(student_json, "sex", cJSON_CreateString("男"));
	cJSON_AddItemToObject(student_json, "status", cJSON_CreateString("damn-single"));
	cJSON_AddItemToObject(student_json, "成績", grades_json);
	cJSON_AddItemToObject(grades_json, "專業課", cJSON_CreateString("awful"));
	cJSON_AddItemToObject(grades_json, "學科競賽", cJSON_CreateString("not bad"));
	cJSON_AddItemToObject(grades_json, "文化素養", cJSON_CreateString("so-so"));
	cJSON_AddItemToObject(student_json, "備註", cJSON_CreateString("這是一條備註"));
	
	output = cJSON_Print(student_json);
	
	if( output == NULL )	printf("error!\r\n");
	else	printf("Info:\r\n %s \r\n", output);
	/////////////////////////////////////////////////////////////////////////////////////
	cJSON_Delete(student_json);
	cJSON_Delete(grades_json);
	free(output);
	/////////////////////////////////////////////////////////////////////////////////////

}

其輸出結果爲:
輸出結果

P.S. 上面這段代碼一開始我在STM32裏面敲,然後用串口調試助手打印信息,結果不行,cJSON_Print(student_json)返回的是NULL,原因大概是因爲由於是在STM32裏面,然後類似於內存分配啥的問題,內存不夠之類(因爲代碼我單條單條在STM32都能實現,但是一次性要打印這麼多數據就崩了)

以上。

參考資料:
全面詳解c語言使用cJSON解析JSON字符
JSON的簡單介紹&cJSON庫使用(一)
cJSON詳解
JSON介紹
cJSON的使用方法
STM32 keil環境下移植cJSON
STM32移植cJSON[注意用free()釋放內存]
CSDN:去掉博客中的圖片水印 /狗頭

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