小言_互联网的博客

Linux(程序设计):30---cJSON库(C语言操作JSON)

870人阅读  评论(0)

一、cJSON库概述

cJSON库的编译安装

  • 下载cJSON源码
git clone https://github.com/DaveGamble/cJSON.git

  • 下载完成之后有一个cJSON目录

  • 下载完成之后进入cJSON目录,在里面建立一个build目录,然后进入build目录,输入cmake ..

   
  1. cd cJSON
  2. mkdir build
  3. cd build
  4. cmake ..

  • 然后回到顶级目录,可以看到目录下生成了一个Makefile文件,此时输入make对cJOSN进行编译

  • 编译完成之后进行安装

  • 默认情况下,cJSON的头文件安装到/usr/local/include/cjson/目录下,动态库文件安装到/usr/local/lib/目录下,相关cmake文件安装到/usr/local/lib/cmake/cJSON/目录下

  • 因为头文件默认安装在/usr/local/include/cjson/目录下,因此编译程序的时候如果用到cJSON.h这个头文件会显示不存在,如下图所示

  • 因此我们需要将/usr/local/include/cjson/cJSON.h移动到/usr/local/include/目录下,如下所示

  • 备注:其实我们不需要将cJSON.h文件从/usr/local/include/cjson/目录下移动到/usr/local/include/目录下,如果不移动的话那么就编写代码时带上include "cjson/cJSON.H"头文件即可,只不过有cjson/前缀比较麻烦

编译运行带有cJSON库的程序

  • 有两种方式:
    • ①方式一:像上面一样,将cJSON安装,然后将cJONS.h拷贝到/usr/local/include/目录下,然后将源码目录下的cJOSN.c文件拷贝到项目目录下
    • ②方式二:不用像上面一样安装cJSON,直接将cJSON源码目录下的cJSON.h和cJSON.c文件拷贝到项目下就可以编译使用了
  • 编译程序时使用下面的命令:

   
  1. # 因为 cJSON源码中使用到了数学函数库, 因此需要使用 -lm选项
  2. gcc cJSON .c demo .c -o demo -lm
  • 编译的过程中可能会遇到的问题:
    • 遇到cJSON.h头文件不识别的问题:确保cJSON.h位于你的程序可以找到的地方,如果在其他地方可以指定gcc -I参数进行编译
    • 不仅要有cJSON.h头文件,程序编译时还要需要cJSON.c文件,因此需要将cJSON库下的cJSON.c拷贝到自己的项目中进行编译
    • cJSON不同版本之间源码不同,因此需要确保使用的cJSON.h和cJSON.c是同一版本的,否则会编译不通过

二、cJSON库重要的数据结构与类型

cJSON结构

  • cJSON结构定义在cJSON.h头文件中,每个JSON对象就是用这个结构表示的

   
  1. /* The cJSON structure: */
  2. typedef struct cJSON {
  3. struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
  4. struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
  5. int type; /* The type of the item, as above. */
  6. char *valuestring; /* The item's string, if type==cJSON_String */
  7. int valueint; /* The item's number, if type==cJSON_Number */
  8. double valuedouble; /* The item's number, if type==cJSON_Number */
  9. char * string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
  10. } cJSON;
  • next、prev:用于遍历数组或对象链的前后向后链表指针
  • child:指向数组或对象的孩节点
  • type:代表一个JSON是value的类型
  • valuestring:如果value是字符串类型,则该值指向于value
  • valueint:如果value是整数类型,则该值指向于value
  • valuedouble:如果value是浮点数类型,则该值指向于value
  • string是key的名字

cJSON支持的类型

  • 下面是一些宏定义,就是cJOSN结构中type字段可以取得值,代表值的类型

   
  1. /* cJSON Types: */
  2. #define cJSON_False 0
  3. #define cJSON_True 1
  4. #define cJSON_NULL 2
  5. #define cJSON_Number 3
  6. #define cJSON_String 4
  7. #define cJSON_Array 5
  8. #define cJSON_Object 6

三、重点函数

cJSON_Parse

cJSON *cJSON_Parse(const char *value);
  • 作用:参数传递一个JSON字符串,将该字符串转换为一个cJSON对象进行返回(该对象是在内存中动态申请的,因此需要用下面的cJSON_Delete进行释放)
  • 返回值:
    • 成功:返回一个指向内存中的cJSON的指针
    • 失败:返回NULL

cJSON_Delete

void cJSON_Delete(cJSON *c);
  • 作用:释放位于堆中的cJSON结构体内存
  • 无返回值
  • 备注:
    • 在使用cJSON_Parse创建cJSON对象之后,如果该对象不再使用了,需要释放该对象,否则导致内存泄漏
    • 其他有些API也会创建cJSON对象,在申请用完之后也需要释放

cJSON_Print

char  *cJSON_Print(cJSON *item);
  • 作用:将cJSON对象解析成一个字符串进行返回,并在堆中开辟一块char*的内存空间存储该字符串
  • 返回值:
    • 成功:返回一个指向char*指针指向位于堆中的JSON字符串
    • 失败:返回NULL
  • 备注:
    • 通过cJSON_Print()可以将cJSON链表中所有的cJSON对象打印出来
    • cJSON_PrintUnformatted()与 cJSON_Print()类似,只是打印输出不带格式,而只是一个 字符串数据
    • 因为返回值是该函数自动申请的,因此在使用完之后需要使用free()释放该函数返回值的内存空间

cJSON_Version

const char* cJSON_Version(void);
  • 作用:将返回当前使用的cJSON库的版本号
  • 返回值:一个表示当前版本的字符串

cJSON_GetArrayItem

cJSON *cJSON_GetArrayItem(cJSON *array,int item);
  • 作用:如果array是一个数组类型的,则返回数组中item索引处的cJSON对象
  • 返回值:
    • 成功:返回一个指向cJSON类型的结构体指针
    • 失败:返回NULL

cJSON_GetArraySize

int cJSON_GetArraySize(cJSON *array);
  • 作用:如果array是一个数组类型,返回数组中对应元素的个数
  • 返回值:
    • 有元素:返回元素的个数
    • 无元素:返回0
  • 与上面类似的接口还有cJSON_GetObjectItem()和cJSON_HashObjectItem()

四、所有函数简介

五、演示案例1

 代码如下


   
  1. //demo1.c
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include "cJSON.h"
  5. #include <string.h>
  6. /**
  7. {
  8. "name": "milo",
  9. "age": 80,
  10. "professional": {专业
  11. "english": 4,
  12. "putonghua": 2,
  13. "computer": 4
  14. },
  15. "languages": ["C++", "C"],
  16. "phone": {
  17. "number": "18620823143",
  18. "type": "home"
  19. },
  20. "courses": [{
  21. "name": "Linux kernel development",
  22. "price": "7.7"
  23. }, {
  24. "name": "Linux server development",
  25. "price": "8.0"
  26. }],
  27. "vip": true,
  28. "address": null
  29. }
  30. */
  31. //打印CJSON
  32. void printfJson(cJSON *json) {
  33. if ( NULL == json) {
  34. return;
  35. }
  36. char *cjson=cJSON_Print(json); //深拷贝
  37. printf( "json:%s\n", cjson);
  38. free(cjson);
  39. }
  40. //释放
  41. void freeJson(cJSON *json) {
  42. if (json != NULL) {
  43. cJSON_Delete(json);
  44. }
  45. }
  46. //创建JSON
  47. cJSON * createJson() {
  48. //创建根节点JSON(最外面大括号的JSON对象)
  49. cJSON *json_root=cJSON_CreateObject();
  50. cJSON_AddItemToObject(json_root, "name", cJSON_CreateString( "milo"));
  51. cJSON_AddNumberToObject(json_root, "age", 80);
  52. //下面是4个内部JSON对象(包含在根JSON内部的)
  53. cJSON *json_professional=cJSON_CreateObject();
  54. cJSON_AddItemToObject(json_professional, "english", cJSON_CreateNumber( 4));
  55. cJSON_AddItemToObject(json_professional, "putonghua", cJSON_CreateNumber( 2));
  56. cJSON_AddItemToObject(json_professional, "computer", cJSON_CreateNumber( 3));
  57. cJSON *json_languages=cJSON_CreateArray(); //注意: 这是一个数组
  58. cJSON_AddItemToArray(json_languages, cJSON_CreateString( "C++"));
  59. cJSON_AddItemToArray(json_languages, cJSON_CreateString( "C"));
  60. cJSON *json_phone=cJSON_CreateObject();
  61. cJSON_AddItemToObject(json_phone, "number", cJSON_CreateString( "18620823143"));
  62. cJSON_AddItemToObject(json_phone, "type", cJSON_CreateString( "home"));
  63. cJSON *json_courses = cJSON_CreateArray(); //注意: courses也是一个数组, 其内部有两个对象
  64. cJSON* json_pItem1 = cJSON_CreateObject();
  65. cJSON_AddItemToObject(json_pItem1, "name", cJSON_CreateString( "Linux kernel development"));
  66. cJSON_AddNumberToObject(json_pItem1, "price", 7.7);
  67. cJSON_AddItemToArray(json_courses, json_pItem1);
  68. cJSON* json_pItem2 = cJSON_CreateObject();
  69. cJSON_AddItemToObject(json_pItem2, "name", cJSON_CreateString( "Linux server development"));
  70. cJSON_AddNumberToObject(json_pItem2, "price", 8.8);
  71. cJSON_AddItemToArray(json_courses, json_pItem2);
  72. //将这个几个内部JSON添加到根节点JSON对象中
  73. cJSON_AddItemToObject(json_root, "professional", json_professional);
  74. cJSON_AddItemToObject(json_root, "languages", json_languages);
  75. cJSON_AddItemToObject(json_root, "phone", json_phone);
  76. cJSON_AddItemToObject(json_root, "courses", json_courses);
  77. cJSON_AddBoolToObject(json_root, "vip", 1);
  78. cJSON_AddNullToObject(json_root, "address");
  79. return json_root;
  80. }
  81. //向已有的cJSON对象中添加数据(此函数以添加到根节点为例)
  82. //如果要添加到根cJSON对象内部的cJSON对象中(例如添加到professional中), 需要解析cJSON对象, 可以参阅下面的analysisJsonObj()函数
  83. //"hobby": ["Basketball", "Football", "badminton"],
  84. void addDataToJson(cJSON *json) {
  85. if ( NULL == json) {
  86. return;
  87. }
  88. cJSON *hobby=cJSON_CreateArray();
  89. cJSON_AddItemToArray(hobby, cJSON_CreateString( "Basketball"));
  90. cJSON_AddItemToArray(hobby, cJSON_CreateString( "Football"));
  91. cJSON_AddItemToArray(hobby, cJSON_CreateString( "badminton"));
  92. /*
  93. CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
  94. */
  95. cJSON_AddItemToObject(json, "hobby", hobby);
  96. printfJson(json);
  97. }
  98. //修改cJSON对象
  99. //例如将 "hobby": ["Basketball", "Football", "badminton"], 修改为"hobby": ["Skating", "dance"],
  100. void updateDataToJson(cJSON *json) {
  101. if ( NULL == json) {
  102. return;
  103. }
  104. cJSON *hobby=cJSON_CreateArray();
  105. cJSON_AddItemToArray(hobby, cJSON_CreateString( "Skating"));
  106. cJSON_AddItemToArray(hobby, cJSON_CreateString( "dance"));
  107. /*
  108. CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
  109. CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
  110. */
  111. //修改替换
  112. cJSON_ReplaceItemInObject(json, "hobby", hobby);
  113. printfJson(json);
  114. }
  115. //删除
  116. //例如删除"hobby": ["Skating", "dance"],
  117. void deleteDataToJson(cJSON *json) {
  118. if ( NULL == json) {
  119. return;
  120. }
  121. /*
  122. CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
  123. */
  124. cJSON_DetachItemFromObject(json, "hobby");
  125. printfJson(json);
  126. }
  127. //解析JSON
  128. void analysisJsonObj(cJSON *json) {
  129. if ( NULL == json) {
  130. return;
  131. }
  132. //解析name
  133. cJSON *json_name = cJSON_GetObjectItem(json, "name");
  134. printf( "root[%s:%s]\n", json_name-> string, json_name->valuestring);
  135. //解析age
  136. cJSON *json_age = cJSON_GetObjectItem(json, "age");
  137. printf( "root[%s:%d]\n", json_age-> string, json_age->valueint);
  138. //解析professional, 通过调用child和next遍历解析
  139. cJSON *json_professional = cJSON_GetObjectItem(json, "professional");
  140. cJSON *json_professional_child = json_professional->child;
  141. while (json_professional_child != NULL) {
  142. printf( "%s[%s:%d]\n", json_professional-> string, json_professional_child-> string, json_professional_child->valueint);
  143. json_professional_child = json_professional_child->next;
  144. }
  145. //解析languages, 注意languages是一个数组
  146. cJSON *json_languages = cJSON_GetObjectItem(json, "languages");
  147. if (json_languages) {
  148. int size = cJSON_GetArraySize(json_languages);
  149. printf( "%s size:%d\n", json_languages-> string, size);
  150. for ( int i = 0; i < size; i++) {
  151. cJSON *json_languages_child =cJSON_GetArrayItem(json_languages, i);
  152. printf( "%s[%d:%s]\n", json_languages-> string, i, json_languages_child->valuestring);
  153. }
  154. }
  155. //解析phone. 另一种方式解析, 直接通过名字获取
  156. cJSON *json_phone = cJSON_GetObjectItem(json, "phone");
  157. cJSON *json_phone_number = cJSON_GetObjectItem(json_phone, "number");
  158. cJSON *json_phone_type = cJSON_GetObjectItem(json_phone, "type");
  159. printf( "%s[%s:%s]\n", json_phone-> string, json_phone_number-> string, json_phone_number->valuestring);
  160. printf( "%s[%s:%s]\n", json_phone-> string, json_phone_type-> string, json_phone_type->valuestring);
  161. //解析courses
  162. cJSON *json_courses = cJSON_GetObjectItem(json, "courses");
  163. if (json_courses) {
  164. int size = cJSON_GetArraySize(json_courses);
  165. printf( "%s size:%d\n", json_courses-> string, size);
  166. for( int i= 0;i<size;i++) {
  167. cJSON *json_array = cJSON_GetArrayItem(json_courses, i);
  168. if (json_array) {
  169. cJSON *json_course_name = cJSON_GetObjectItem(json_array, "name");
  170. cJSON *json_course_price = cJSON_GetObjectItem(json_array, "price");
  171. printf( "%s[%s:%.1lf]\n", json_courses-> string, json_course_name-> string, json_course_name->valuedouble);
  172. printf( "%s[%s:%.1lf]\n", json_courses-> string, json_course_price-> string, json_course_price->valuedouble);
  173. }
  174. }
  175. }
  176. //解析vip, vip是布尔值, 有两种方式解析获取
  177. cJSON *json_vip = cJSON_GetObjectItem(json, "vip");
  178. /*
  179. if (json_vip->type == cJSON_True) {
  180. printf("root[%s:true]\n", json_vip->string);
  181. } else if (json_vip->type == cJSON_False) {
  182. printf("root[%s:false]\n", json_vip->string);
  183. } else {
  184. printf("root[%s:false]\n", json_vip->string);
  185. }
  186. */
  187. cJSON_bool bvip = cJSON_IsBool(json_vip);
  188. if (bvip == cJSON_True) { //cJSON_False
  189. printf( "root[%s:true]\n", json_vip-> string);
  190. } else {
  191. printf( "root[%s:false]\n", json_vip-> string);
  192. }
  193. //解析address
  194. cJSON *json_address = cJSON_GetObjectItem(json, "address");
  195. if (json_address->type ==cJSON_NULL) {
  196. printf( "root[%s:null]\n", json_address-> string);
  197. }
  198. }
  199. //获取cJSON对象的类型, 并同时打印值
  200. static void printJsonObjvalue(const cJSON *json) {
  201. if ( NULL == json) {
  202. printf( "NULL object!\n");
  203. return;
  204. }
  205. switch (json->type) {
  206. case cJSON_False:
  207. printf( "%s: false\n", json-> string);
  208. break;
  209. case cJSON_True:
  210. printf( "%s: true\n", json-> string);
  211. break;
  212. case cJSON_NULL:
  213. printf( "%s: cJSON_NULL\n", json-> string);
  214. break;
  215. case cJSON_Number:
  216. printf( "%s: %d, %f\n", json-> string, json->valueint, json->valuedouble);
  217. break;
  218. case cJSON_String:
  219. printf( "%s: %s\n", json-> string, json->valuestring);
  220. break;
  221. case cJSON_Array:
  222. printf( "%s: cJSON_Array\n", json-> string);
  223. break;
  224. case cJSON_Object:
  225. printf( "%s: cJSON_Object\n", json-> string);
  226. break;
  227. default:
  228. printf( "unknown type\n");
  229. break;
  230. }
  231. }
  232. void analysisJsonPrint(cJSON *json) {
  233. if ( NULL == json) {
  234. return;
  235. }
  236. cJSON *json_name = cJSON_GetObjectItem(json, "name");
  237. printJsonObjvalue(json_name);
  238. cJSON *json_age = cJSON_GetObjectItem(json, "age");
  239. printJsonObjvalue(json_age);
  240. cJSON *json_professional = cJSON_GetObjectItem(json, "professional");
  241. cJSON *json_professional_child = json_professional->child;
  242. while (json_professional_child != NULL) {
  243. printJsonObjvalue(json_professional_child);
  244. json_professional_child = json_professional_child->next;
  245. }
  246. cJSON *json_languages = cJSON_GetObjectItem(json, "languages");
  247. if ( NULL == json_languages) {
  248. int size = cJSON_GetArraySize(json_languages);
  249. printf( "%s size:%d\n", json_languages-> string, size);
  250. for ( int i = 0; i < size; i++) {
  251. cJSON *json_languages_child = cJSON_GetArrayItem(json_languages, i);
  252. printJsonObjvalue(json_languages_child);
  253. }
  254. }
  255. cJSON *json_phone = cJSON_GetObjectItem(json, "phone");
  256. cJSON *json_phone_number = cJSON_GetObjectItem(json_phone, "number");
  257. cJSON *json_phone_type = cJSON_GetObjectItem(json_phone, "type");
  258. printJsonObjvalue(json_phone_number);
  259. printJsonObjvalue(json_phone_type);
  260. cJSON *json_courses = cJSON_GetObjectItem(json, "courses");
  261. if (json_courses) {
  262. int size = cJSON_GetArraySize(json_courses);
  263. printf( "%s size:%d\n", json_courses-> string, size);
  264. for( int i= 0;i<size;i++) {
  265. cJSON *arrayItem = cJSON_GetArrayItem(json_courses, i);
  266. if ( NULL != arrayItem) {
  267. cJSON *json_course_name = cJSON_GetObjectItem(arrayItem, "name");
  268. cJSON *json_course_price = cJSON_GetObjectItem(arrayItem, "price");
  269. printJsonObjvalue(json_course_name);
  270. printJsonObjvalue(json_course_price);
  271. }
  272. }
  273. }
  274. cJSON *json_vip = cJSON_GetObjectItem(json, "vip");
  275. printJsonObjvalue(json_vip);
  276. cJSON *json_address = cJSON_GetObjectItem(json, "address");
  277. printJsonObjvalue(json_address);
  278. }
  279. //读取JSON
  280. cJSON* readJsonFile(char *fileName) {
  281. if ( NULL == fileName) {
  282. return NULL;
  283. }
  284. FILE *fp = NULL;
  285. cJSON *json = NULL;
  286. char line[ 1024] = { 0};
  287. char *data = NULL;
  288. //打开一个文本文件,文件必须存在,只允许读
  289. fp = fopen(fileName, "r");
  290. if ( NULL != fp) {
  291. //seek末尾
  292. fseek(fp, 0, SEEK_END);
  293. //读取文件大小
  294. long len = ftell(fp);
  295. //seek起始位值
  296. fseek(fp, 0, SEEK_SET);
  297. data = ( char*) malloc(len + 1);
  298. fread(data, 1, len, fp);
  299. fclose(fp);
  300. }
  301. printf( "readJsonFile data:%s\n", data);
  302. cJSON *json_root = cJSON_Parse(data);
  303. if ( NULL == json_root) {
  304. printf( "cJSON_Parse error:%s\n", cJSON_GetErrorPtr());
  305. }
  306. if ( NULL != data) {
  307. free(data);
  308. }
  309. return json_root;
  310. }
  311. //保存JSON
  312. void writeJsonFile(char *fileName, cJSON *json) {
  313. if ( NULL == json || NULL == fileName) {
  314. return;
  315. }
  316. char *cjson=cJSON_Print(json);
  317. FILE *fp = NULL;
  318. //新建一个文本文件,已存在的文件将内容清空,允许读写
  319. fp = fopen(fileName, "w+");
  320. if ( NULL != fp) {
  321. fwrite(cjson, strlen(cjson), 1,fp);
  322. fclose(fp);
  323. }
  324. if ( NULL != cjson) {
  325. free(cjson);
  326. }
  327. }
  328. void test1() {
  329. cJSON *json_root = createJson();
  330. //打印
  331. printfJson(json_root);
  332. //解析json
  333. analysisJsonObj(json_root);
  334. //解析json
  335. analysisJsonPrint(json_root);
  336. freeJson(json_root);
  337. }
  338. void test2() {
  339. char *fileName = "./person.json";
  340. //读取json
  341. cJSON *json_root = readJsonFile(fileName);
  342. //解析json
  343. analysisJsonObj(json_root);
  344. //解析json
  345. analysisJsonPrint(json_root);
  346. //写入json文件
  347. writeJsonFile(fileName, json_root);
  348. //释放
  349. freeJson(json_root);
  350. }
  351. //增删改
  352. void test3() {
  353. cJSON *json_root = createJson();
  354. addDataToJson(json_root);
  355. updateDataToJson(json_root);
  356. deleteDataToJson(json_root);
  357. freeJson(json_root);
  358. }
  359. int main(int argc, char *argv[]) {
  360. printf( "-----------------------------------\n");
  361. test1();
  362. printf( "-----------------------------------\n");
  363. test2();
  364. printf( "-----------------------------------\n");
  365. test3();
  366. printf( "-----------------------------------\n");
  367. return 0;
  368. }
  • 编译如下:
gcc cJSON.c demo1.c -o demo1 -lm

  • 效果如下(只截取部分):

 

六、演示案例2

 代码如下


   
  1. //comment_test.c
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <sys/time.h>
  5. #include "cJSON.h"
  6. #include <string.h>
  7. //评论
  8. typedef struct COMMENT
  9. {
  10. int user_id;
  11. int msg_id;
  12. char* comment;
  13. int click_count;
  14. int like_count;
  15. int reply_count;
  16. int is_new_reply;
  17. long add_time;
  18. } COMMENT;
  19. //例如
  20. /**
  21. json对象
  22. {
  23. "user_id":1,
  24. "msg_id":1,
  25. "comment":"json",
  26. "click_count":0,
  27. "like_count":0,
  28. "reply_count":0,
  29. "is_new_reply":0,
  30. "add_time":0,
  31. }
  32. */
  33. //获取当前时间毫秒数
  34. long getCurrentTime()
  35. {
  36. struct timeval tv;
  37. gettimeofday(&tv, NULL);
  38. //毫秒
  39. long time_sec = tv.tv_sec* 1000 + tv.tv_usec/ 1000;
  40. return time_sec;
  41. }
  42. //打印CJSON
  43. void printfJson(cJSON *json) {
  44. if ( NULL == json) {
  45. return;
  46. }
  47. char *cjson=cJSON_Print(json); //深拷贝
  48. printf( "json:%s\n", cjson);
  49. free(cjson); //因为调用了cJSON_Print(), 因此需要手动释放资源
  50. }
  51. void freeComment(COMMENT *comment) {
  52. if (comment != NULL) {
  53. if (comment->comment != NULL) {
  54. free(comment->comment);
  55. comment->comment = NULL;
  56. }
  57. free(comment);
  58. comment = NULL;
  59. }
  60. }
  61. void freeJson(cJSON *json) {
  62. if (json != NULL) {
  63. cJSON_Delete(json);
  64. }
  65. }
  66. //将结构体转成cJSON
  67. cJSON *convertToJson(COMMENT *comment)
  68. {
  69. if (comment == NULL)
  70. return NULL;
  71. //创建json
  72. cJSON *json=cJSON_CreateObject();
  73. //将 "user_id" 添加到 "json" 节点
  74. cJSON_AddNumberToObject(json, "user_id", comment->user_id);
  75. cJSON_AddNumberToObject(json, "msg_id", comment->msg_id);
  76. cJSON_AddItemToObject(json, "comment", cJSON_CreateString(comment->comment)); //调用cJSON_CreateString()将字符串转换为JSON中的字符串类型,否则报错
  77. cJSON_AddNumberToObject(json, "click_count", comment->click_count);
  78. cJSON_AddNumberToObject(json, "like_count", comment->like_count);
  79. cJSON_AddNumberToObject(json, "reply_count", comment->reply_count);
  80. cJSON_AddNumberToObject(json, "is_new_reply", comment->is_new_reply);
  81. cJSON_AddNumberToObject(json, "add_time", comment->add_time);
  82. //user_id等的value都是int类型的,因此使用cJSON_AddNumberToObject. 而comment是字符串类型的,因此使用cJSON_AddItemToObject
  83. return json;
  84. }
  85. //解析cJSON对象, 将cJSON赋值给结构体
  86. COMMENT* convertToComment(cJSON *json)
  87. {
  88. if ( NULL == json) {
  89. return NULL;
  90. }
  91. //通cJSON对象中获取内容
  92. cJSON *json_user_id = cJSON_GetObjectItem(json, "user_id");
  93. cJSON *json_msg_id = cJSON_GetObjectItem(json, "msg_id");
  94. cJSON *json_comment = cJSON_GetObjectItem(json, "comment");
  95. cJSON *json_click_count = cJSON_GetObjectItem(json, "click_count");
  96. cJSON *json_like_count = cJSON_GetObjectItem(json, "like_count");
  97. cJSON *json_reply_count = cJSON_GetObjectItem(json, "reply_count");
  98. cJSON *json_is_new_reply = cJSON_GetObjectItem(json, "is_new_reply");
  99. cJSON *json_add_time = cJSON_GetObjectItem(json, "add_time");
  100. //将内容赋值给结构体
  101. COMMENT *comment = (COMMENT *) malloc( sizeof(COMMENT));
  102. comment->user_id = json_user_id->valueint; //user_id等是使用int来存储的, 因此使用cJSON对象的valueint成员来获取(下同)
  103. comment->msg_id = json_msg_id->valueint;
  104. comment->comment=( char *) malloc( 256);
  105. memset(comment->comment, 0, 256);
  106. strcat(comment->comment, json_comment->valuestring); //comment是使用字符串来存储的, 因此使用cJSON对象的valuestring成员来获取(下同)
  107. comment->click_count = json_click_count->valueint;
  108. comment->like_count = json_like_count->valueint;
  109. comment->reply_count = json_reply_count->valueint;
  110. comment->is_new_reply = json_is_new_reply->valueint;
  111. comment->add_time = ( long)(json_add_time->valuedouble); //C中使用long来存储时间, 在cJSON中使用double来存储
  112. return comment;
  113. }
  114. //从数据中读取数据
  115. void readJsonFromData(char *data) {
  116. cJSON *json=cJSON_Parse(data); //将data数据构建成cJSON结构
  117. //打印json
  118. printfJson(json);
  119. COMMENT* comment = convertToComment(json);
  120. if (comment != NULL) {
  121. comment->like_count = 77;
  122. comment->reply_count = 99;
  123. //转为json
  124. cJSON *childjson = convertToJson(comment);
  125. //打印json
  126. printfJson(childjson);
  127. //释放对象
  128. freeComment(comment);
  129. //
  130. freeJson(childjson);
  131. }
  132. //cJSON_Parse()返回的cJSON对象需要手动释放资源
  133. freeJson(json);
  134. }
  135. //保存JSON
  136. void writeJsonFile(cJSON *json) {
  137. if ( NULL == json) {
  138. return;
  139. }
  140. char *cjson=cJSON_Print(json);
  141. FILE *fp = NULL;
  142. char *fileName = "./comment.json";
  143. fp = fopen(fileName, "w+");
  144. if ( NULL != fp) {
  145. fwrite(cjson, strlen(cjson), 1,fp);
  146. fclose(fp);
  147. }
  148. if (cjson != NULL) {
  149. free(cjson);
  150. }
  151. }
  152. //读取JSON
  153. void readJsonFile() {
  154. FILE *fp = NULL;
  155. char *out;
  156. char line[ 1024] = { 0};
  157. char *fileName = "./comment.json";
  158. //打开一个文本文件,文件必须存在,只允许读
  159. fp = fopen(fileName, "r");
  160. //seek末尾
  161. fseek(fp, 0, SEEK_END);
  162. //读取文件大小
  163. long len = ftell(fp);
  164. //seek起始位值
  165. fseek(fp, 0, SEEK_SET);
  166. char *data = ( char*) malloc(len + 1);
  167. fread(data, 1, len, fp);
  168. if (fp != NULL) {
  169. fclose(fp);
  170. }
  171. //读取
  172. readJsonFromData(data);
  173. if ( NULL != data) {
  174. free(data);
  175. }
  176. }
  177. COMMENT *createComment() {
  178. COMMENT *comment = (COMMENT *) malloc( sizeof(COMMENT));
  179. comment->user_id = 1;
  180. comment->msg_id = 10000;
  181. comment->comment=( char *) malloc( 256);
  182. memset(comment->comment, 0, 256);
  183. sprintf(comment->comment, "我赞同楼主");
  184. comment->click_count = 0;
  185. comment->like_count = 0;
  186. comment->reply_count = 0;
  187. comment->is_new_reply = 0;
  188. comment->add_time = getCurrentTime();
  189. return comment;
  190. }
  191. void test1() {
  192. COMMENT *comment = createComment();
  193. //转为json
  194. cJSON *json = convertToJson(comment);
  195. //保存json
  196. writeJsonFile(json);
  197. freeComment(comment);
  198. freeJson(json);
  199. }
  200. void test2() {
  201. //读取json
  202. readJsonFile();
  203. }
  204. int main(int argc, char *argv[]) {
  205. test1();
  206. test2();
  207. return 0;
  208. }
  • 编译如下:
gcc cJSON.c comment_test.c -o comment_test -lm

  • 效果如下: 


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