cJSON是使用C语言编写,用来创建、解析JSON文件的库。cJSON特点就是工程文件简单,只有一个.c
和一个.h
,但提供函数接口功能齐全,麻雀虽小五脏俱全,使得在嵌入式工程中使用起来得心应手。
https://github.com/DaveGamble/cJSON
只需拉取cJSON.c
和cJSON.h
即可。
给出如下JSON格式示例
{
"messageType": 2,
"messageId": "16493268950279230864908057508987",
"imei": "864908057508987898607B1192180035422",
"iccid": "898607B1192180035422",
"reportTime": "2022-12-16 15:49:00",
"gpsData":
[
{
"Longitude":31.23453232,
"Latitude":118.45345431
},
{
"Longitude":31.23453245,
"Latitude":118.45345443
}
{
"Longitude":31.23453255,
"Latitude":118.45345453
}
]
}
1、先创建根节点指针
cJSON *root = NULL;
root = cJSON_Parse(msg);
cJSON其实是个结构体类型,被定义如下,cJSON_Parse
接口拿到我们的msg
数据后会创建一个cJSON结构实例
,我们创建的cJSON结构体指针
root,会指向这个cJSON结构体实例
。既然是实例,就会申请内存。所以最后我们一定不要释放掉这块内存,否则将导致内存泄漏
/* 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;
cJSON结构体其实是一个抽象的键值对。
他通过成员:前节点、后节点、子节点,来实现JSON结构的嵌套,JSON结构最终在内存中是以一个链表的形式存在。
struct cJSON *next; //前节点
struct cJSON *prev; //后节点
struct cJSON *child;//子节点
而每个节点通过以下成员存储键值
char *valuestring;
int valueint;
double valuedouble;
2、获取键值对
是int类型键值就指向valueint
,是字符串类型指向valuestring
,字符串数据我们可以用strcpy拷贝出来
cJSON *msgType = NULL;
msgType = cJSON_GetObjectItem(root , "messageType" );
int type = msgType ->valueint
char id[21];
cJSON *iccid = NULL;
iccid = cJSON_GetObjectItem(root , "iccid" );
strcpy(id, iccid ->valuestring);
3、获取数组
如果出现像示例中gpsData这种JSON数组,数组下面又嵌套着新的JSON数据的,我们将使用以下API
cJSON* gpsDataArray = NULL;
cJSON* gpsPoint = NULL;
int gpsArraySize = 0;
double Longitude = 0//经度
double Latitude = 0 //纬度
gpsDataArray = cJSON_GetObjectItem(root, "gpsData");
gpsArraySize = cJSON_GetArraySize(gpsDataArray);
for(i = 0; i < gpsArraySize ; i++)
{
gpsPoint = cJSON_GetArrayItem(gpsDataArray , i);
Longitude = cJSON_GetObjectItem(gpsPoint , "Longitude");
Latitude = cJSON_GetObjectItem(gpsPoint , "Latitude");
}
4、释放内存 !
cJSON_Delete(root);
现在我们试图组装《cJSON解析》
中的示例
1、同样,创建根节点
cJSON* root = NULL;
root = cJSON_CreateObject();
2、添加键值对成员
cJSON_AddNumberToObject(root , "messageType", 2);
cJSON_AddStringToObject(root , "messageId", "16493268950279230864908057508987");
cJSON_AddStringToObject(root , "imei", "864908057508987898607B1192180035422");
cJSON_AddStringToObject(root , "iccid", "898607B1192180035422");
cJSON_AddStringToObject(root , "reportTime","2022-12-16 15:49:00");
3、添加数组
和解析相反,我们应该先创建gps点,然后把点添加到数组,再把数组添加到根节点
//先创建3个gps点
cJSON* gpsData1 = NULL;
gpsData2 = cJSON_CreateObject();
cJSON_AddNumberToObject(gpsData1 ,"Longitude", 31.23453232);
cJSON_AddNumberToObject(gpsData1 ,"Latitude", 118.45345431;
cJSON* gpsData2 = NULL;
gpsData2 = cJSON_CreateObject();
cJSON_AddNumberToObject(gpsData2 ,"Longitude", 31.23453245);
cJSON_AddNumberToObject(gpsData2 ,"Latitude", 118.45345443;
cJSON* gpsData3 = NULL;
gpsData3 = cJSON_CreateObject();
cJSON_AddNumberToObject(gpsData3 ,"Longitude", 31.23453255);
cJSON_AddNumberToObject(gpsData3 ,"Latitude", 118.45345453;
//创建数组,把gps点添加到gps数组
cJSON* gpsArray = NULL;
gpsArray = cJSON_CreateArray();
cJSON_AddItemToArray(gpsArray ,gpsData1 );
cJSON_AddItemToArray(gpsArray ,gpsData2 );
cJSON_AddItemToArray(gpsArray ,gpsData3 );
//把gps数组添加到根节点
cJSON_AddItemToObject(root,"gpsData",gpsArray );
4、输出组装的JSON
char *msg;
msg = cJSON_Print(root);
5、依然要记得释放内存
cJSON_Delete(root);