飞道的博客

全面详解c语言使用cJSON解析JSON字符

454人阅读  评论(0)

 

为什么选择cJSON来解析JSON字符串?因为简洁又简单,而且效率又快,cJSON工程文件也非常简单,仅一个.c文件和一个.h文件!

如果要自己写的话就是重造轮子了,况且效率上也不一定会比cJSON更好!

且文件体积大小不到30k,源代码思路也非常清晰,也非常适合研究。

点我下载cJSON

当我们下载好cJSON只需要把.c和.h文件包含文件拷贝到我们工程目录下,并将头文件和实现文件包含进来就可以使用了!

cJSON使用数据结构链表的方式来存储js对象。

 

 


  
  1. typedef struct cJSON { //cJSON结构体
  2. struct cJSON*next,*prev; /* 遍历数组或对象链的前向或后向链表指针*/
  3. struct cJSON *child; /*数组或对象的孩子节点*/
  4. int type; /* key的类型*/
  5. char *valuestring; /*字符串值*/
  6. int valueint; /* 整数值*/
  7. double valuedouble; /* 浮点数值*/
  8. char * string; /* key的名字*/
  9. } cJSON;

 

 

正所谓万丈高楼平地起,先从最简单的开始!

 

 

先来介绍四个常用的cJSON函数:

 

cJSON *cJSON_Parse(const char *value);

 

作用:将一个JSON数据包,按照cJSON结构体的结构序列化整个数据包,并在堆中开辟一块内存存储cJSON结构体

返回值:成功返回一个指向内存块中的cJSON的指针,失败返回NULL

 

cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);

作用:获取JSON字符串字段值

返回值:成功返回一个指向cJSON类型的结构体指针,失败返回NULL

 

 

char  *cJSON_Print(cJSON *item);

作用:将cJSON数据解析成JSON字符串,并在堆中开辟一块char*的内存空间存储JSON字符串

 

返回值:成功返回一个char*指针该指针指向位于堆中JSON字符串,失败返回NULL

 

 

void   cJSON_Delete(cJSON *c);

作用:释放位于堆中cJSON结构体内存

 

返回值:无

 

假如说有这样的一个JSON字符串

 


  
  1. {
  2. "test_1": "0"
  3. "test_2": "1"
  4. "test_3": "2"
  5. }  //json_string
 //json_string

这是最简单的JSON字符串

我们首先要先将这个字符串打包成cJSON数据格式

 

cJSON* cjson = cJSON_Parse(json_string);

打包后使用if语句或三目表达式判断一下是否将JSON字符串打包成cJSON数据格式


  
  1. if(cjson == NULL){
  2. printf( "json pack into cjson error...")
  3. }
  4. else{ //打包成功调用cJSON_Print打印输出
  5. cJSON_Print(cjson);
  6. }

 


  
  1. 然后依次获取json字符串中的每个字段的值并打印输出
  2. //cJSON_GetObjectltem返回的是一个cJSON结构体所以我们可以通过函数返回结构体的方式选择返回类型!
  3. char* test_1_string = cJSON_GetObjectItem(cjson, "test_1")->valuestring;
  4. char* test_2_string = cJSON_GetObjectItem(cjson, "test_2")->valuestring;
  5. char* test_3_string = cJSON_GetObjectItem(cjson, "test_3")->valuestring;

  
  1. //打印输出
  2. printf( "%s",*test_1_string);
  3. printf( "%s",*test_2_string);
  4. printf( "%s",*test_3_string);

最后别忘记释放内存

 

 


  
  1. //delete cjson
  2. cJSON_Delete(cjson);
  3. cJSON_Delete(test_arr);
  4. cJSON_Delete(arr_item);

 

完整代码:

 


  
  1. #include <stdio.h>
  2. #include <cJSON.h>
  3. int main(){
  4. char* json_string =\
  5. //用char* 模拟一个JSON字符串
  6. "{"\
  7. "test_1": "0"\
  8. "test_2": "1"\
  9. "test_3": "2"\
  10. "}";
  11. //JSON字符串到cJSON格式
  12. cJSON* cjson = cJSON_Parse(json_string);
  13. //判断cJSON_Parse函数返回值确定是否打包成功
  14. if(cjson == NULL){
  15. printf( "json pack into cjson error...")
  16. }
  17. else{ //打包成功调用cJSON_Print打印输出
  18. cJSON_Print(cjson);
  19. }
  20. //获取字段值
  21. //cJSON_GetObjectltem返回的是一个cJSON结构体所以我们可以通过函数返回结构体的方式选择返回类型!
  22. char* test_1_string = cJSON_GetObjectltem(cjson, "test_1")->valuestring;
  23. char* test_2_string = cJSON_GetObjectltem(cjson, "test_2")->valuestring;
  24. char* test_3_string = cJSON_GetObjectltem(cjson, "test_3")->valuestring;
  25. //打印输出
  26. printf( "%s",*test_1_string);
  27. printf( "%s",*test_2_string);
  28. printf( "%s",*test_3_string);
  29. //delete cjson
  30. cJSON_Delete(cjson);
  31. }

是不是很easy?下面来教大家如何使用cJSON解析数组!


  
  1. {
  2. "test_1": "1",
  3. "test_2": "2",
  4. "test_arr":[{
  5. {
  6. "test_1": "arr_1",
  7. "test_2": "arr_2",
  8. "test_3": "arr_3"
  9. },
  10. {
  11. "test_1": "1",
  12. "test_2": "2",
  13. "test_3": "3"
  14. }
  15. }],
  16. "test_3" : "3"
  17. } //json_arr string

在开始前介绍一个函数

int	  cJSON_GetArraySize(cJSON *array);

作用:获取数组成员对象个数
返回值:数组成员对象个数

 


首先第一步打包

 

cJSON* cjson = cJSON_Parse(json_arr_string);

第二步判断打包是否成功

 

 


  
  1. if(cjson == NULL){
  2. printf( "cjson error...")
  3. }
  4. else{ //打包成功调用cJSON_Print打印输出
  5. cJSON_Print(cjson);
  6. }

第三步获取数组对象

cJSON* test_arr = cJSON_GetObjectltem(cjson,"test_arr");

第四步获取数组对象个数便于循环

int arr_size = cJSON_GetArraySize(test_arr);//return arr_size 2

第五步获取test_arr数组对象孩子节点

cJSON* arr_item = test_arr->child;//子对象

第六步循环获取数组下每个字段的值并使用cJSON_Print打印:


  
  1. for( int i = 0;i <=(arr_size -1) /*0*/;++i){
  2. cJSON_Print(cJSON_GetObjectItem(arr_item, "test_1"));
  3. cJSON_Print(cJSON_GetObjectItem(arr_item, "test_2"));
  4. cJSON_Print(cJSON_GetObjectItem(arr_item, "test_3"));
  5. arr_item = arr_item->next; //下一个子对象
  6. }

最后别忘记释放

 

 

cJSON_Delete(cjson);

完整代码:

 

 


  
  1. #include <stdio.h>
  2. #include <cJSON.h>
  3. int main(){
  4. char* json_string =\
  5. //用char* 模拟一个JSON字符串
  6. “{”,\
  7. "test_1": "1",\
  8. "test_2": "2",\
  9. "test_arr": "[{",\
  10. "{",\
  11. "test_1": "arr_1",\
  12. "test_2": "arr_2",\
  13. "test_3": "arr_3",\
  14. "}",\
  15. "{"\
  16. "test_1": "1",\
  17. "test_2": "2",\
  18. "test_3": "3",\
  19. "}",\
  20. "}]",\
  21. "test_3" : "3",\
  22. "}" //json_arr string;
  23. //第一步打包JSON字符串
  24. cJSON* cjson = cJSON_Parse(json_arr_string);
  25. //判断是否打包成功
  26. if(cjson == NULL){
  27. printf( "cjson error…")
  28. }
  29. else{ //打包成功调用cJSON_Print打印输出
  30. cJSON_Print(cjson);
  31. }
  32. //获取数组对象
  33. cJSON* test_arr = cJSON_GetObjectltem(cjson, "test_arr");
  34. //获取数组对象个数便于循环
  35. int arr_size = cJSON_GetArraySize(test_arr); //return arr_size 2
  36. //获取test_arr数组对象孩子节点
  37. cJSON* arr_item = test_arr->child; //子对象
  38. //循环获取数组下每个字段的值并使用cJSON_Print打印
  39. for( int i = 0;i <=(arr_size -1) /*0*/;++i){
  40. cJSON_Print(cJSON_GetObjectItem(arr_item, "test_1"));
  41. cJSON_Print(cJSON_GetObjectItem(arr_item, "test_2"));
  42. cJSON_Print(cJSON_GetObjectItem(arr_item, "test_3"));
  43. arr_item = arr_item->next; //下一个子对象
  44. }
  45. //delete cjson 这里只需要释放cjson即可,因为其它的都指向它
  46. cJSON_Delete(cjson);

 

 

如果觉得博主写的不错,可以加技术交流群吖:815060222


转载:https://blog.csdn.net/bjbz_cxy/article/details/79173603
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场