參考路徑: https://blog.csdn.net/qq_44045338/article/details/107654286
cJSON詳解及其C函數接口使用
JSON簡介
JSON語法
CJSON介紹
cJSON源碼
cJSON數據結構與常用接口
數據結構定義
常用接口
cJSON_Parse
cJSON_Delete
cJSON_Print
cJSON_Version
cJSON_GetArrayItem
與cJSON_GetObjectItem()類似的接口:
類型判斷接口
創建cJSON對象接口
添加cJSON對象到鏈表
從cJSON對象中刪除一個cJSON對象
創建並添加到鏈表
使用實例
解析數據實例
解析數據實例一
實例運行結果
解析數據實例二
實例運行結果
添加數據實例
實例
運行結果:
JSON簡介
JSON:JavaScript對象表示法(JavaScript Object Notation)。是一種輕量級的數據交換格式。它基於ECMAScript的一個子集。JSON采用完全獨立於語言的文本格式,但是也使用了類似C語音家族的習慣(包括C、C++、C#、Java、JavaScript、Perl、Python等)。這些特性使JSON成為理想的數據交換語言。易於人閱讀和編寫,同時也易於機器解析和生成(一般用於提升網絡傳輸速率)。
JSON解析器和JSON庫支持許多不同的編程語言。JSON文本格式在語法上與創建JavaScript對象的代碼相同。由於這種相似性,無需解釋器,JavaScript程序能夠使用內建的eval()函數,用JSON數據來生成原生的JavaScript對象。
JSON是存儲和交換文本信息的語法,類似XML。但JSON比XML更小、更快、更易解析;且JSON具有自我描述性、語法簡單,易於理解。
JSON語法
JSON語法是JavaScript對象表示法語法的子集:
數據在鍵/值對中;
數據由逗號分隔;
花括號保存對象,也稱一個文檔對象;
方括號保存數組,每個數組成員用逗號隔開,並且每個數組成員可以是文檔對象或者數組或者鍵值對。
JSON的三種語法:
鍵/值對key:value,用半角冒號分割。比如"name":"Faye"。
文檔對象JSON對象寫在花括號中,可以包含多個鍵/值對。比如{"name":"Ami", "address":"上海"}。
數組JSON數組在方括號中書寫:數組成員可以是對象、值,也可以是數組(只要有意義)。比如{"love": ["c","c++","python","java"]}。
JSON的值可以是:數字(整數或浮點數)、字符串(在雙引號中)、邏輯值(true或false)、數組(在方括號中)、對象(在花括號中)、null。
JSON兩種結構:
對象:對象在js中表示為“{}”括起來的內容,數據結構為{key:value,key:value,...}的鍵值對的結構,在面向對象的語言中,key為對象的屬性,value為對應的屬性值,所以很容易理解,取值方法為 對象.key 獲取屬性值;
數組:數組在js中是中括號“[]”括起來的內容,數據結構為["java","javascript","vb",...],取值方式和所有語言中一樣,使用索引獲取。
經過對象、數組2種結構就可以組合成復雜的數據結構了。
CJSON介紹
cJSON是一個僅有一個.h文件,一個.c文件組成的JSON解析器,它是由純C(ANSI C89)實現的,跨平台性較好。cJSON是采用鏈表存儲的。
cJSON庫在使用的時候只需要如下兩步:將cJSON.c(或者庫文件)和cJSON.h添加到項目中即可;如果在命令行中進行鏈接還需要加上-lm表示鏈接math庫。
cJSON源碼
git clone https://github.com/tjcshx/cJson.git
cJSON數據結構與常用接口
整體來講,cJSON庫的數據結構和函數命名接口非常規范,基本上一看就懂,非常容易理解。
數據結構定義
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
next、prev用於遍歷數組或對象鏈的前向后向鏈表指針;child指向數組或對象的孩子節點;type是value的類型;valuestring是字符串值;valueint是整數值;valuedouble是浮點數值;string是key的名字。還是非常容易理解的。
常用接口
cJSON_Parse
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
作用:將一個JSON字符串,按照cJSON結構體的結構序列化整個數據包,並在堆中開辟一塊內存存儲cJSON結構體。
返回值:成功返回一個指向內存塊中的cJSON的指針,失敗返回NULL。
cJSON_Delete
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
作用:釋放位於堆中cJSON結構體內存。
返回值:無
注意:在使用cJSON_Parse()獲取cJSON指針后,若不再使用了,則需要調用cJSON_Delete()對其釋放,否則會導致內存泄漏。
cJSON_Print
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
作用:將cJSON數據解析成JSON字符串,並在堆中開辟一塊char*的內存空間存儲JSON字符串。cJSON_PrintUnformatted()與cJSON_Print()類似,只是打印輸出不帶格式,而只是一個字符串數據。
返回值:成功返回一個char*指針該指針指向位於堆中JSON字符串,失敗返回NULL。
注意:通過cJSON_Print()可以將cJSON鏈表中所有的cJSON對象打印出來,但是需要手動去釋放對應的資源:free(char *)。
cJSON_Version
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
作用:獲取當前使用的cJSON庫的版本號。
返回值:返回一個字符串數據。
cJSON_GetArrayItem
* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
作用:從object的cJSON鏈中尋找key為string的cJSON對象。
返回值:成功返回一個指向cJSON類型的結構體指針,失敗返回NULL。
與cJSON_GetObjectItem()類似的接口:
* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* Check if the item is a string and return its valuestring */
CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
類型判斷接口
下面的接口用於判斷具體cJSON指針指向的item類型:
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
創建cJSON對象接口
下面的接口用於創建指定類型的cJSON數據結構對象:
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* These utilities create an Array of count items. */
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
添加cJSON對象到鏈表
下面的接口用於將創建的cJSON對象添加到鏈表中:
/* Append item to the specified array/object. */
CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
從cJSON對象中刪除一個cJSON對象
下面的接口用於從現有的cJSON鏈表中刪除一個對象:
/* Remove/Detatch items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
創建並添加到鏈表
下面的接口用於創建並添加cJSON對象到指定的鏈表(簡化操作):
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
使用實例
解析數據實例
解析數據實例一
只有一層鍵值,即無嵌套鍵值。
#include <stdio.h>
#include <string.h>
#include "cJSON.h"
int main (int argc, char **argv)
{
char resolve_buf[] = "{\"method\":\"thing.service.property.set\",\"id\":\"412505849\",
\"LightSwitch\":1,\"version\":\"1.0.0\"}";
cJSON *json = NULL;
cJSON *json_val = NULL;
cJSON *json_timestamp = NULL;
printf("%s\n", resolve_buf);
json = cJSON_Parse(resolve_buf);
if (NULL == json)
{
printf("cJSON_Parse error:%s\n", cJSON_GetErrorPtr());
}
json_val = cJSON_GetObjectItem(json, "LightSwitch");
if (cJSON_Number == json_val->type)
{
printf("LightSwitch:%d\n", json_val->valueint);
}
cJSON_Delete(json);
return 0;
} /* ----- End of main() ----- */
實例運行結果
解析數據實例二
有多層鍵值,即有嵌套鍵值。例如:
{
"method": "thing.service.property.set",
"id": "412505849",
"params": {
"LightSwitch": 1
},
"version": "1.0.0"
}
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
void printJson(cJSON * root)//以遞歸的方式打印json的最內層鍵值對
{
int i = 0;
for(; i<cJSON_GetArraySize(root); i++) //遍歷最外層json鍵值對
{
cJSON * item = cJSON_GetArrayItem(root, i);
if(cJSON_Object == item->type) //如果對應鍵的值仍為cJSON_Object就遞歸調用printJson
printJson(item);
else //值不為json對象就直接打印出鍵和值
{
printf("%s->", item->string);
printf("%s\n", cJSON_Print(item));
}
}
}
int main()
{
char * jsonStr = "{\"method\":\"thing.service.property.set\",\"id\":\"412505849\",\"params\":
{\"LightSwitch\":1},\"version\":\"1.0.0\"}";
cJSON * root = NULL;
cJSON * item = NULL;
root = cJSON_Parse(jsonStr);
if (!root)
{
printf("Error before: [%s]\n",cJSON_GetErrorPtr());
}
else
{
printf("%s\n", "有格式的方式打印Json:");
printf("%s\n\n", cJSON_Print(root));
printf("%s\n", "無格式方式打印json:");
printf("%s\n\n", cJSON_PrintUnformatted(root));
printf("%s\n", "一步一步的獲取name 鍵值對:");
printf("%s\n", "獲取params下的cjson對象:");
item = cJSON_GetObjectItem(root, "params");
printf("%s\n", cJSON_Print(item));
printf("%s\n", "獲取params下的cjson對象");
item = cJSON_GetObjectItem(item, "LightSwitch");
printf("%s\n", cJSON_Print(item));
printf("\n%s\n", "打印json所有最內層鍵值對:");
printJson(root);
}
return 0;
}
實例運行結果
添加數據實例
實例
添加具有內部嵌套鍵值的。
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
int main(int argc, char **argv)
{
char *cjson_str = NULL;
cJSON * root = cJSON_CreateObject();
cJSON * item = cJSON_CreateObject();
cJSON * next = cJSON_CreateObject();
cJSON_AddItemToObject(root, "root", cJSON_CreateNumber(0));//根節點下添加
cJSON_AddItemToObject(root, "method", cJSON_CreateString("thing.service.property.set"));
cJSON_AddItemToObject(root, "id", cJSON_CreateString("412505849"));
cJSON_AddItemToObject(root, "params", item); //添加嵌套鍵值
cJSON_AddItemToObject(item, "LightSwitch", cJSON_CreateNumber(1));//內部嵌套鍵值
root節點下添加semantic節點
cJSON_AddItemToObject(root, "version", cJSON_CreateString("1.0.0"));
cjson_str = cJSON_Print(root);
printf("first json:\n%s\n", cjson_str);
free(cjson_str);
cJSON_AddStringToObject(next, "number", "13423452334");
cJSON_AddNumberToObject(next, "age", 35);
cJSON_AddBoolToObject(next, "man", 1);
cjson_str = cJSON_Print(root);
printf("second json:\n%s\n", cjson_str);
free(cjson_str);
cJSON_Delete(root);
return 0;
}
運行結果:
————————————————
版權聲明:本文為CSDN博主「TianJinCheng'Blog」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_44045338/article/details/107654286