使用CJSON 解析JSON 结构体数组【典型】 您所在的位置:网站首页 vue取json数组的键值名 使用CJSON 解析JSON 结构体数组【典型】

使用CJSON 解析JSON 结构体数组【典型】

2023-12-23 16:05| 来源: 网络整理| 查看: 265

1.CJSON数据结构定义 #define cJSON_False 0 #define cJSON_True 1 #define cJSON_NULL 2 #define cJSON_Number 3 #define cJSON_String 4 #define cJSON_Array 5 //数组 #define cJSON_Object 6 //对象or单键名 typedef struct cJSON { struct cJSON *next,*prev; /*遍历数组或对象链的前向或后向链表指针*/ struct cJSON *child; /*数组或对象的子节点*/ int type; /* key键的类型,上面宏定义的7中之一*/ char *valuestring; /*字符串值, if type==cJSON_String */ int valueint; /* 整型数值, if type==cJSON_Number */ double valuedouble; /* 浮点数值, if type==cJSON_Number */ char *string; /* key键的名字 */ } cJSON;

说明:

1、cJSON是使用链表来存储数据的,其访问方式很像一颗树。每一个节点可以有兄弟节点,通过next/prev指针来查找,它类似双向链表;每个节点也可以有孩子节点,通过child指针来访问,进入下一层。只有节点是对象或数组时才可以有孩子节点。

2、type是键(key)的类型,一共有7种取值,分别是:False,Ture,NULL,Number,String,Array(数组),Object(对象或单键名)。

若是Number类型,则valueint或valuedouble中存储着值。若期望的是int,则访问valueint,若期望的是double,则访问valuedouble,可以得到值。若是String类型的,则valuestring中存储着值,可以访问valuestring得到值。

3、string中存放的是这个节点的名字,可理解为key的名称。

2.常用的解析函数 /* 第一个 *函数功能:将一个JSON数据包序列化,并开辟堆内存存储获取的cJSON对象; *返回值:成功返回一个指向cJSON对象的指针;失败则返回NULL */ extern cJSON *cJSON_Parse(const char *value);//从源数据中,获取未整理的JSON对象 /* 第二个 *函数功能:根据单键名(cjson对象)获取对应的值 *参数: *objec:第一个函数中获取的句柄 * string:需要获取的对象 *返回值: */ extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); /* 第三个 *函数功能: *返回值: */ extern int cJSON_GetArraySize(cJSON *array);//获取cjson对象数组成员的个数 /* 第四个 *函数功能:根据下标获取cjosn对象数组中对应元素的对象 *参数: array 数组名 item 数组的下标元素 *返回值:元素的键值;失败则返回NULL */ extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); /* 第五个 *作用:与Parse成对出现,释放Parse操作时,产生的位于堆中cJSON结构体内存; *返回值:无 */ extern void cJSON_Delete(cJSON *c);//删除cjson对象,释放链表占用的内存空间

3.解析:包含两个键值对的结构体(单层)

第一层结构体;第二层键值对

步骤:Parse格式化==》cJSON_GetObjectItem根据键名获取键值

char text[]="{\"name\":\"Tom\",\"age\":18}"; cJSON * root = cJSON_Parse(text); if(!root) { printf("no json\n"); return -1; } //name cJSON *name = cJSON_GetObjectItem(root, "name"); if (!name) { printf("no name!\n"); return -1; } else{ printf("%s\n",name->valuestring); } //age cJSON *age = cJSON_GetObjectItem(root, "age"); if (!age) { printf("no age!\n"); return -1; } else{ printf("%d\n",age->valueint); } cJSON_Delete(root);

4.解析:键值对嵌套 { "semantic": { "slots": { "name": "张三" } }, "rc": 0, "operation": "CALL", "service": "telephone", "text": "打电话给张三" }

5.解析:包含键值对结构体的数组

第一层数组;第二层结构体;第三层键值对;

步骤:Parse格式化==》IsArray判断是否数组==》GetArraySize获取数组元素个数==》cJSON_GetArrayItem按照下标检索数组元素==》cJSON_GetObjectItem根据元素中的单键名获取键值

int main(){ char text[]="[{\"name\":\"Tom1\",\"age\":18},{\"name\":\"Tom2\",\"age\":19},{\"name\":\"Tom3\",\"age\":20},{\"name\":\"Tom4\",\"age\":21}]"; cJSON * root = cJSON_Parse(text); if(!root) { printf("no json\n"); return -1; } if (!cJSON_IsArray(root)){ printf("no Array\n"); return -1; } //数组长度 int array_size = cJSON_GetArraySize(root); cJSON *item; cJSON *name; cJSON *age; for(int i=0; i< array_size; i++) { item = cJSON_GetArrayItem(root, i); name = cJSON_GetObjectItem(item, "name"); if (!name) { printf("no name!\n"); return -1; } printf("%s\t",name->valuestring); age = cJSON_GetObjectItem(item, "age"); if (!age) { printf("no age!\n"); return -1; } printf("%d\n",age->valueint); } return 0; } cJSON_Delete(root);

6.解析结构体数组的JSON串

与5的区别在于,第一层是键值对(值:是结构体数组)

{ "people":[ {"firstName":"z","lastName":"Jason","email":"[email protected]","height":1.67}, {"lastName":"jadena","email":"[email protected]","age":8,"height":1.17}, {"email":"[email protected]","firstName":"z","lastName":"Juliet","age":36,"height":1.55} ] }

(1)调用cJSON_Parse()函数,解析JSON数据包。

(2)调用一次cJSON_GetObjectItem()函数,获取到数组people。【重点区别!!】

(3)对刚取出来的数组people,调用cJSON_GetArraySize()函数,来获取数组中对象的个数。然后,多次调用cJSON_GetArrayItem()函数,逐个读取数组中对象的内容。

(4)通过cJSON_Delete(),释放cJSON_Parse()分配出来的内存空间。

例程如下:例程较长,见文章末尾。

7.混合解析:键值对结构体+数组混合嵌套 { "results": [ { "currentConfirmedCount":3247, "currentConfirmedIncr":-37, "confirmedCount":127336, "confirmedIncr":39, "suspectedCount":9919, "suspectedIncr":23, "curedCount":118392, "curedIncr":76, "deadCount":5697, "deadIncr":0, "seriousCount":500, "seriousIncr":-10, "globalStatistics": { "currentConfirmedCount":40083221, "confirmedCount":255222728, "curedCount":210013003, "deadCount":5126504, "currentConfirmedIncr":370347, "confirmedIncr":485719, "curedIncr":108221, "deadIncr":7151, "yesterdayConfirmedCountIncr":485714 }, "generalRemark":"", "remark1":"易感人群:人群普遍易感。老年人及有基础疾病者感染后病情较重,儿童及婴幼儿也有发病", "remark2":"潜伏期:一般为 3~7 天,最长不超过 14 天,潜伏期内可能存在传染性,其中无症状病例传染性非常罕见", "remark3":"宿主:野生动物,可能为中华菊头蝠", "remark4":"", "remark5":"", "note1":"病毒:SARS-CoV-2,其导致疾病命名 COVID-19", "note2":"传染源:新冠肺炎的患者。无症状感染者也可能成为传染源。", "note3":"传播途径:经呼吸道飞沫、接触传播是主要的传播途径。气溶胶传播和消化道等传播途径尚待明确。", "updateTime":1637145079410 } ], "success":true }

而当待解析数据同时包含了“结构体数组”时:

第一步,先利用cJSON_GetArraySize获取数组元素个数;

第二步,使用cJSON_GetArrayItem(数组名,元素下标)方式来检索数组中对应的元素;

第三步,判断该元素是否包含了直接的对象,即该元素的类型是否是cJSON_Object;

第四步,使用cJSON_GetObjectItem(元素名,单键名)的方式获取单键名所对应的键值;

仅解析部分: int parseData(uint8_t *str) { int ret = 0; cJSON *root, *result_arr; cJSON *result, *global; time_t updateTime; struct tm *time; root = cJSON_Parse((const char *)str); //创建JSON解析对象,返回JSON格式是否正确 if (root != 0) { rt_kprintf("JSON format ok, start parse!!!\n"); //通过调用cJSON_GetObjectItem,获取到数组results!!!! result_arr = cJSON_GetObjectItem(root, "results");//results是服务器下发JSON数据的数组名 if(result_arr->type == cJSON_Array) { // rt_kprintf("result is array\n"); //由于提前知道数组results只包含1个元素,因此不用再调用cJSON_GetArraySize来获取元素个数,而是直接读第0个元素的值 result = cJSON_GetArrayItem(result_arr, 0);//在数组result_arr中检索第0个元素 if(result->type == cJSON_Object)//如果第0个元素的类型是“对象” { // rt_kprintf("result_arr[0] is object\n"); /* china data parse */ dataChina.currentConfirmedCount = cJSON_GetObjectItem(result, "currentConfirmedCount")->valueint; dataChina.currentConfirmedIncr = cJSON_GetObjectItem(result, "currentConfirmedIncr")->valueint; dataChina.confirmedCount = cJSON_GetObjectItem(result, "confirmedCount")->valueint; dataChina.confirmedIncr = cJSON_GetObjectItem(result, "confirmedIncr")->valueint; dataChina.curedCount = cJSON_GetObjectItem(result, "curedCount")->valueint; dataChina.curedIncr = cJSON_GetObjectItem(result, "curedIncr")->valueint; dataChina.deadCount = cJSON_GetObjectItem(result, "deadCount")->valueint; dataChina.deadIncr = cJSON_GetObjectItem(result, "deadIncr")->valueint; rt_kprintf("**********china ncov data**********\n"); rt_kprintf("%-23s: %8d, %-23s: %8d\n", "currentConfirmedCount", dataChina.currentConfirmedCount, "currentConfirmedIncr", dataChina.currentConfirmedIncr); rt_kprintf("%-23s: %8d, %-23s: %8d\n", "confirmedCount", dataChina.confirmedCount, "confirmedIncr", dataChina.confirmedIncr); rt_kprintf("%-23s: %8d, %-23s: %8d\n", "curedCount", dataChina.curedCount, "curedIncr", dataChina.curedIncr); rt_kprintf("%-23s: %8d, %-23s: %8d\n", "deadCount", dataChina.deadCount, "deadIncr", dataChina.deadIncr); /* global data parse */ global = cJSON_GetObjectItem(result, "globalStatistics"); if(global->type == cJSON_Object) { dataGlobal.currentConfirmedCount = cJSON_GetObjectItem(global, "currentConfirmedCount")->valueint; dataGlobal.currentConfirmedIncr = cJSON_GetObjectItem(global, "currentConfirmedIncr")->valueint; dataGlobal.confirmedCount = cJSON_GetObjectItem(global, "confirmedCount")->valueint; dataGlobal.confirmedIncr = cJSON_GetObjectItem(global, "confirmedIncr")->valueint; dataGlobal.curedCount = cJSON_GetObjectItem(global, "curedCount")->valueint; dataGlobal.curedIncr = cJSON_GetObjectItem(global, "curedIncr")->valueint; dataGlobal.deadCount = cJSON_GetObjectItem(global, "deadCount")->valueint; dataGlobal.deadIncr = cJSON_GetObjectItem(global, "deadIncr")->valueint; rt_kprintf("\n**********global ncov data**********\n"); rt_kprintf("%-23s: %8d, %-23s: %8d\n", "currentConfirmedCount", dataGlobal.currentConfirmedCount, "currentConfirmedIncr", dataGlobal.currentConfirmedIncr); rt_kprintf("%-23s: %8d, %-23s: %8d\n", "confirmedCount", dataGlobal.confirmedCount, "confirmedIncr", dataGlobal.confirmedIncr); rt_kprintf("%-23s: %8d, %-23s: %8d\n", "curedCount", dataGlobal.curedCount, "curedIncr", dataGlobal.curedIncr); rt_kprintf("%-23s: %8d, %-23s: %8d\n", "deadCount", dataGlobal.deadCount, "deadIncr", dataGlobal.deadIncr); } else return 1; /* 毫秒级时间戳转字符串 */ updateTime = (time_t )(cJSON_GetObjectItem(result, "updateTime")->valuedouble / 1000); updateTime += 8 * 60 * 60; /* UTC8校正 */ time = localtime(&updateTime); /* 格式化时间 */ strftime(dataChina.updateTime, 20, "%m-%d %H:%M", time); rt_kprintf("update: %s\r\n", dataChina.updateTime);/* 06-24 11:21 */ gui_show_ncov_data(dataChina, dataGlobal);//???屏幕输出相关!!!! } else return 1; } else return 1; rt_kprintf("\nparse complete \n"); } else { rt_kprintf("JSON format error:%s\n", cJSON_GetErrorPtr()); //输出json格式错误信息 return 1; } cJSON_Delete(root); return ret; }

8.两种数组的解析 8.1包含多个键值对的结构体数组

 以上格式可以使用如下解析方法:

【重点:利用数组或对象的后向链表指针】

cJSON *ip_arry = cJSON_GetObjectItem( clientlist, "iplist"); //clientlist 是使用 cjson对象 if( NULL != ip_arry ){ cJSON *client_list = ip_arry->child; while( client_list != NULL ){ char * ip = cJSON_GetObjectItem( client_list , "ip")->valuestring ; char * mask = cJSON_GetObjectItem( client_list , "mask")->valuestring ; printf("ip: %s mask: %s",ip,mask); client_list = client_list->next ; } }

8.2 包含多个键值的单键数组

 方法类似结构体数组

解析方法如下:第一步获取键名,第二步获取数组个数,第三步按照元素下标获取元素对象!

cJSON *MAC_arry = cJSON_GetObjectItem( clientlist, "Maclist"); if( MAC_arry != NULL ){ int array_size = cJSON_GetArraySize ( MAC_arry ); for( iCnt = 0 ; iCnt < array_size ; iCnt ++ ){ cJSON * pSub = cJSON_GetArrayItem(MAC_arry, iCnt); if(NULL == pSub ){ continue ; } char * ivalue = pSub->valuestring ; printf("Maclist[%d] : %s",iCnt,ivalue); } }

附件: 本文6段的例程 #include #include #include #include #include #include "cJSON.h" typedef struct { int id; char firstName[32]; char lastName[32]; char email[64]; int age; float height; }people; void dofile(char *filename);/* Read a file, parse, render back, etc. */ int main(int argc, char **argv) { // dofile("json_str1.txt"); // dofile("json_str2.txt"); dofile("json_str3.txt"); return 0; } //parse a key-value pair int cJSON_to_str(char *json_string, char *str_val) { cJSON *root=cJSON_Parse(json_string); if (!root) { printf("Error before: [%s]\n",cJSON_GetErrorPtr()); return -1; } else { cJSON *item=cJSON_GetObjectItem(root,"firstName"); if(item!=NULL) { printf("cJSON_GetObjectItem: type=%d, key is %s, value is %s\n",item->type,item->string,item->valuestring); memcpy(str_val,item->valuestring,strlen(item->valuestring)); } cJSON_Delete(root); } return 0; } //parse a object to struct int cJSON_to_struct(char *json_string, people *person) { cJSON *item; cJSON *root=cJSON_Parse(json_string); if (!root) { printf("Error before: [%s]\n",cJSON_GetErrorPtr()); return -1; } else { cJSON *object=cJSON_GetObjectItem(root,"person"); if(object==NULL) { printf("Error before: [%s]\n",cJSON_GetErrorPtr()); cJSON_Delete(root); return -1; } printf("cJSON_GetObjectItem: type=%d, key is %s, value is %s\n",object->type,object->string,object->valuestring); if(object!=NULL) { item=cJSON_GetObjectItem(object,"firstName"); if(item!=NULL) { printf("cJSON_GetObjectItem: type=%d, string is %s, valuestring=%s\n",item->type,item->string,item->valuestring); memcpy(person->firstName,item->valuestring,strlen(item->valuestring)); } item=cJSON_GetObjectItem(object,"lastName"); if(item!=NULL) { printf("cJSON_GetObjectItem: type=%d, string is %s, valuestring=%s\n",item->type,item->string,item->valuestring); memcpy(person->lastName,item->valuestring,strlen(item->valuestring)); } item=cJSON_GetObjectItem(object,"email"); if(item!=NULL) { printf("cJSON_GetObjectItem: type=%d, string is %s, valuestring=%s\n",item->type,item->string,item->valuestring); memcpy(person->email,item->valuestring,strlen(item->valuestring)); } item=cJSON_GetObjectItem(object,"age"); if(item!=NULL) { printf("cJSON_GetObjectItem: type=%d, string is %s, valueint=%d\n",item->type,item->string,item->valueint); person->age=item->valueint; } else { printf("cJSON_GetObjectItem: get age failed\n"); } item=cJSON_GetObjectItem(object,"height"); if(item!=NULL) { printf("cJSON_GetObjectItem: type=%d, string is %s, valuedouble=%f\n",item->type,item->string,item->valuedouble); person->height=item->valuedouble; } } cJSON_Delete(root); } return 0; } //parse a struct array int cJSON_to_struct_array(char *text, people worker[]) { cJSON *json,*arrayItem,*item,*object; int i; json=cJSON_Parse(text); if (!json) { printf("Error before: [%s]\n",cJSON_GetErrorPtr()); } else { arrayItem=cJSON_GetObjectItem(json,"people"); if(arrayItem!=NULL) { int size=cJSON_GetArraySize(arrayItem); printf("cJSON_GetArraySize: size=%d\n",size); for(i=0;itype,item->string); memcpy(worker[i].firstName,item->valuestring,strlen(item->valuestring)); } item=cJSON_GetObjectItem(object,"lastName"); if(item!=NULL) { printf("cJSON_GetObjectItem: type=%d, string is %s, valuestring=%s\n",item->type,item->string,item->valuestring); memcpy(worker[i].lastName,item->valuestring,strlen(item->valuestring)); } item=cJSON_GetObjectItem(object,"email"); if(item!=NULL) { printf("cJSON_GetObjectItem: type=%d, string is %s, valuestring=%s\n",item->type,item->string,item->valuestring); memcpy(worker[i].email,item->valuestring,strlen(item->valuestring)); } item=cJSON_GetObjectItem(object,"age"); if(item!=NULL) { printf("cJSON_GetObjectItem: type=%d, string is %s, valueint=%d\n",item->type,item->string,item->valueint); worker[i].age=item->valueint; } else { printf("cJSON_GetObjectItem: get age failed\n"); } item=cJSON_GetObjectItem(object,"height"); if(item!=NULL) { printf("cJSON_GetObjectItem: type=%d, string is %s, value=%f\n",item->type,item->string,item->valuedouble); worker[i].height=item->valuedouble; } } } for(i=0;i


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有