当前位置:   article > 正文

CJSON库的学习_cjson库学习

cjson库学习

目录

一、JSON简介

二、 JSON语法

​​​​​​三、 CJSON简介:

四、 CJSON数据结构

五、使用CJSON构造JSON

1. cJSON常用库函数介绍

2. CJSON构造JSON实例代码

(1)!!!编译过程中有两个注意的点:

3. 使用cJSON解析JSON实例代码


一、JSON简介

  1.  JSON(JavaScript object Notation),即JavaScript 对象符号,是一种轻量级的数据格式;【其本质就是字符串
  2.  它采用完全独立于编程语言的文本格式来存储和表示数据,语法简洁,层次结构清晰,易于人阅读和编写,同时也易于机器解析和生成,有效的提升了网络传送效率。
  3.  因为它完全独立于编程语言所以支持跨平台开发;
  4.  JSON 的名称中虽然带有JavaScript,但这是指其语法规则是参考JavaScript对象的,而不是指只能用于JavaScript 语言。
  5.  因为JSON本身就是参考JavaScript 对象的规则定义的,其语法与JavaScript定义对象的语法几乎完全相同。

二、 JSON语法

  1.  JSON可以将数据转换为字符串,接着在网络中或者程序里面传递这个字符串,最后可以还原成各个编程语言所支持的数据格式;
  2.  JSON是一个无序的键值对(key / value)集合;
    • JSON以"{“开始,以”}"结束,允许嵌套使用
    • 每个key(关键字)和value(值)成对出现,关键字和值之间使用":"分隔
    • 键/值对之间用","分隔
    • 在这些字符前后允许存在无意义的空白符
    • 数组(Array)用方括号(“[]”)表示。
    • 对象(0bject)用大括号(“{}”)表示。
    • 名称/值对(name/value)组合成数组和对象。
    • 名称(name)置于双引号中,值(value)有字符串、数值、布尔值、null、对象和数组。
    • 并列的数据之间用逗号(“,”)分隔
  • 在线的JSON解析网站如下:JSON解析

  • 如下是一个实际的例子,来体会一下JSON:

  1. {
  2. "name": "JK",
  3. "age": 18,
  4. "height": 175,
  5. "sex": false,
  6. "address": {
  7. "country": "China",
  8. "tel": 123456
  9. },
  10. "subject": ["语文", "数学", "英语"],
  11. "grade": [1, 2, 3],
  12. "student": [{
  13. "name": "wsf",
  14. "age": 23,
  15. "sex": true
  16. },
  17. {
  18. "name": "rs",
  19. "age": 25,
  20. "sex": true
  21. }
  22. ]
  23. }
  • JSON树可视化

​​​​​​三、 CJSON简介:

  1. CJSON对象的实现采用了树形结构,每一个对象就是树的一个节点,每个节点由cJSON这个结构体组成,对象中的元素也由cJSON这个结构体组成。同一层的对象和元素是双向链表结构,由next和prev指针链接。不同层的对象或元素由child指针链接起来。type表示对象或元素类型,string表示对象或节点的名称。元素的值存储在valuestring, valueint和valuedouble中;

  2. cJSON是一个使用C语言编写的JSON数据解析器,具有超轻便,可移植,单文件的特点,使用MIT开源协议。

  3. 要使用CJSON,直接把项目从Github上clone下来,接着把CJSON.h,CJSON.c这两个源文件加入到工程中就行,使用时include CJSON.h头文件就行;

四、 CJSON数据结构

  • cJSON使用cJSON结构体来表示一个JSON数据,定义在cJSON.h中,源码如下:

  1. //逻辑值的宏定义
  2. #define cJSON_Invalid (0)
  3. #define cJSON_False (1 << 0)
  4. #define cJSON_True (1 << 1)
  5. #define cJSON_NULL (1 << 2)
  6. #define cJSON_Number (1 << 3)
  7. #define cJSON_String (1 << 4)
  8. #define cJSON_Array (1 << 5)
  9. #define cJSON_Object (1 << 6)
  10. #define cJSON_Raw (1 << 7) /* raw json */
  11. #define cJSON_IsReference 256
  12. #define cJSON_StringIsConst 512
  13. /* The cJSON structure: */
  14. typedef struct cJSON
  15. {
  16. /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
  17. struct cJSON *next;
  18. struct cJSON *prev;
  19. /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
  20. struct cJSON *child;
  21. /* The type of the item, as above. */
  22. int type;
  23. /* The item's string, if type==cJSON_String and type == cJSON_Raw */
  24. char *valuestring;
  25. /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
  26. int valueint;
  27. /* The item's number, if type==cJSON_Number */
  28. double valuedouble;
  29. /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
  30. char *string;
  31. } cJSON;

 
  
  1.  首先,CJSON不是将一整段JSON数据全抽象出来,而是将其中的一条JSON数据抽象出来,也就是一个键值对,用上面的结构体 strcut cJSON 来表示,其中用来存放值的成员列表如下:
    1. String:用于表示该键值对的名称;
    2. type:用于表示该键值对中值的类型;
    3. valuestring:如果键值类型(type)是字符串,则将该指针指向键值;
    4. valueint:如果键值类型(type)是整数,则将该指针指向键值;
    5. valuedouble:如果键值类型(type)是浮点数,则将该指针指向键值;
  2.  一段完整的JSON数据中由很多键值对组成,并且涉及到键值对的查找、删除、添加,所以使用链表来存储整段JSON数据,如上面的代码所示:
    1. next指针:指向下一个键值对
    2. prev指针指向上一个键值对
  3.  因为JSON数据支持嵌套,所以一个键值对的值会是一个新的JSON数据对象(一条新的链表),也有可能是一个数组,方便起见,在cJSON中,数组也表示为一个数组对象,用链表存储,所以:在键值对结构体中,当该键值对的值是一个嵌套的JSON数据或者一个数组时,由child指针指向该条新链表;
  4.  链表中的一些概念:
    1. 头指针:指向链表头结点的指针;
    2. 头结点:不存放有效数据,方便链表操作;
    3. 首节点:第一个存放有效数据的节点;
    4. 尾节点:最后一个存放有效数据的节点;

五、使用CJSON构造JSON

1. cJSON常用库函数介绍

  1. extern cJSON * cJSON_CreateObject(void); //创建对象
  2. extern cJSON * cJSON_CreateArray(void); //创建数组
  3. extern cJSON * cJSON_CreateIntArray(const int *numbers, int count);//创建整型数组
  4. extern cJSON * cJSON_CreateDoubleArray(const double *numbers, int count);//创建双浮点型数组
  5. extern cJSON* cJSON_AddNullToObject(cJSON * const object, const char * const name);//在对象中添加null
  6. extern cJSON* cJSON_AddTrueToObject(cJSON * const object, const char * const name);//在对象中添加true
  7. extern cJSON* cJSON_AddFalseToObject(cJSON * const object, const char * const name);//在对象中添加false
  8. extern cJSON* cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);//在对象中添加数字
  9. extern cJSON* cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);//在对象中添加字符串
  10. extern cJSON_bool cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); //在对象中添加项目
  11. extern cJSON_bool cJSON_AddItemToArray(cJSON *array, cJSON *item);//在数组中添加项目
  12. extern char * cJSON_Print(const cJSON *item);//JSON数据结构转换为JSON字符串---有格式
  13. extern char * cJSON_PrintUnformatted(const cJSON *item); //JSON数据结构转换为JSON字符串---无格式
  14. extern void cJSON_Delete(cJSON *item); //清除结构体

2. CJSON构造JSON实例代码

  1. #include "string.h"
  2. #include "cJSON.h"
  3. #include "stdio.h"
  4. int main()
  5. {
  6. // 创建头指针
  7. cJSON *JSON_Root = NULL;
  8. // 创建头结点,并将头指针指向头结点(可以看做是一个树的根root)
  9. JSON_Root = cJSON_CreateObject();
  10. // 添加一条字符串类型的JSON数据
  11. cJSON_AddStringToObject(JSON_Root, "name", "zhuhua");
  12. // 添加一条浮点类型的JSON数据(添加一个链表结点)到root下
  13. cJSON_AddNumberToObject(JSON_Root, "height", 66.6666);
  14. // 添加一条整数型的JSON数据(链表结点)
  15. cJSON_AddNumberToObject(JSON_Root, "grade", 100);
  16. // 添加一个嵌套的JSON数据(添加一个链表节点, 又一个《对象》)
  17. cJSON *timeCode = cJSON_CreateObject();
  18. // true
  19. cJSON_AddTrueToObject(timeCode, "Sex");
  20. cJSON_AddStringToObject(timeCode, "datatime", "20220811");
  21. cJSON_AddFalseToObject(timeCode, "Judge");
  22. // 最后把这个对象加入到root下
  23. cJSON_AddItemToObject(JSON_Root, "TIMECODE", timeCode);
  24. // 再次嵌套,加入一个数组类型的JSON数据,在timecode结点之下(添加一个链表结点)
  25. cJSON *dataCode = cJSON_CreateArray();
  26. // 两种方式添加
  27. cJSON_AddStringToObject(dataCode, "", "English");
  28. cJSON_AddItemToArray(dataCode, cJSON_CreateString("zhuzhuzhu"));
  29. cJSON_AddStringToObject(dataCode, "", "huahuahua");
  30. cJSON_AddNumberToObject(dataCode, "number", 300);
  31. // 将datacode (array)结点添加到timecode 对象结点下(同样数组也可以有对象数据, 甚至数组中数据类型也可以不一样,但这样理解上不太好)
  32. cJSON_AddItemToObject(timeCode, "DATACODE", dataCode);
  33. // 最后将JSON数据结构转换为字符串, 并且输出
  34. char *strForJson = cJSON_Print(JSON_Root);
  35. printf("json字符串:%s\n", strForJson);
  36. // 将字符串存入到文件中
  37. FILE *FCJ = NULL;
  38. FILE *FCJ1 = NULL;
  39. FCJ = fopen("data.txt", "w");
  40. FCJ1 = fopen("data1.txt", "w");
  41. int i = 0;
  42. for (i = 0; i < strlen(strForJson); ++i)
  43. {
  44. fprintf(FCJ, "%c", strForJson[i]);
  45. fputc(strForJson[i], FCJ1);
  46. }
  47. fclose(FCJ);
  48. fclose(FCJ1);
  49. // 清除结构体
  50. cJSON_Delete(JSON_Root);
  51. return 0;
  52. }

  • 输出结果如下:

(1)!!!编译过程中有两个注意的点:

  1. 提示头文件中报unknown type name ‘size_t’错误:

    1. 原因及解决方案:

      1. 原因在测试c文件中加入了string.h的头文件,并且放在了cJSON.h的后面;

      2. 解决:一定要把string.h放在cJSON头文件的前面;

  2. 提示找不到pow和floor函数:

    1. 解决方案:需要链接math库libm(可以查一下libc相关)

  3. 编译语句

  1. gcc cJson.c CJSONTest.c -o uim -lm
  2. 最后./uim执行即可;

3. 使用cJSON解析JSON实例代码

  1. #include <stdio.h>
  2. #include "cJSON.h"
  3. int main()
  4. {
  5. // 定义JSON字符串
  6. char json_string[]="{\"name\":\"zhuhua\",\
  7. \"height\":66.666600,\"grade\":100,\"TIMECODE\":{\"Sex\":true,\"datatime\":\"20220811\",\"Judge\":false,\"DATACODE\":[\"English\",\"zhuzhuzhu\",\"huahuahua\",300]}}";//定义JSON字符串
  8. // 将JSON字符串转换成JSON结构体
  9. cJSON *JSON_ROOT = cJSON_Parse(json_string);
  10. // 判断转换是否成功
  11. if (JSON_ROOT == NULL)
  12. {
  13. printf("cjson error.......\n");
  14. }
  15. else
  16. {
  17. printf("%s\n", cJSON_Print(JSON_ROOT));
  18. }
  19. printf("提取数据\n");
  20. // 解析字符串 找keyvalue
  21. char *name = cJSON_GetObjectItem(JSON_ROOT, "name")->valuestring;
  22. // 打印看一下效果
  23. printf("%s\n", name);
  24. double height = cJSON_GetObjectItem(JSON_ROOT, "height")->valuedouble;
  25. printf("%lf\n", height);
  26. int grade = cJSON_GetObjectItem(JSON_ROOT, "grade")->valueint;
  27. printf("%d\n", grade);
  28. // 对象和数组的接收
  29. cJSON *obj_timeCode = cJSON_GetObjectItem(JSON_ROOT, "TIMECODE"); // 解析对象
  30. cJSON *arr_dataCode = cJSON_GetObjectItem(obj_timeCode, "DATACODE"); // 解析数组 一层一层来
  31. int sex = cJSON_GetObjectItem(obj_timeCode, "Sex")->type; // 解析逻辑值————输出逻辑值对应的宏定义数值
  32. printf("%d\n", sex);
  33. char *datatime = cJSON_GetObjectItem(obj_timeCode, "datatime")->valuestring;
  34. printf("%s\n", datatime);
  35. int judge = cJSON_GetObjectItem(obj_timeCode, "Judge")->type; // 解析逻辑值————输出逻辑值对应的宏定义数值
  36. printf("%d\n", judge);
  37. // 数组的处理 先获取数组的成员个数
  38. int arr_size = cJSON_GetArraySize(arr_dataCode);
  39. printf("arrsize: %d\n", arr_size);
  40. int i = 0;
  41. for (i = 0; i < arr_size - 1; ++i)
  42. {
  43. printf("%s\n", cJSON_GetArrayItem(arr_dataCode, i)->valuestring);
  44. }
  45. printf("%d\n", cJSON_GetArrayItem(arr_dataCode, arr_size - 1)->valueint);
  46. // 清除结构体
  47. cJSON_Delete(JSON_ROOT);
  48. return 0;
  49. }

  • 运行结果如下

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/908463
推荐阅读
相关标签
  

闽ICP备14008679号