JSON是什么
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。JSON 使用 Javascript语法来描述数据对象,但是 JSON 仍然独立于语言和平台。
JSON 基本语法
- 数据以
key :value
(名称/值) 的形式存在
- 数据由逗号
,
分隔
- 大括号
{}
保存对象
- 中括号
[]
保存数组,数组可以包含多个对象
例如:
1
| { name : C Primer pluse, pages : 626 }
|
JSON值(value)的类型
1 2 3 4 5 6 7 8
| #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
|
cJSON又是个啥
cJSON是一个基于C的JSON解析库,这个库非常简短,源码内容只包含一个cJSON.h
头文件和一个cJSON.c
源文件,支持JSON的解析和封装,需要调用时,只需要#include "cJSON.h"
就可以使用了。
cJSON源文件开源项目地址:https://sourceforge.net/projects/cjson/。
cJSON编程实例
例子1
先演示一个最简单的JSON数据,如何使用cJSON库来解析。
用于测试JSON数据,我们先用一个char型的字符串了保存,注意,由于JSON对象的key和value都需要使用引号(数值或逻辑型value除外),所以,使用C语言的字符串来保存JSON数据,在遇到引号时,要加反斜杠来转义。
解析JSON数据时,首先要调用 cJSON_Parse()
这个函数,将JSON数据解析为 cJSON
型的对象:
1
| cJSON *srcJsonData = cJSON_Parse(jsonData);
|
然后就可以使用cJSON库中提供的各种函数来操作这个对象。比如 :
1
| value = cJSON_GetObjectItem(srcJsonData,"name");
|
就是通过 cJSON_GetObjectItem()
来获取JSON数据中的一项数据,并通过指定key的方式来获取对应的value。
整个测试程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include <stdio.h> #include <stdlib.h> #include "cJSON.h"
void main(void) { char jsonData[] = "{\"name\":\"C Primer pluse\",\"pages\":626}"; cJSON *srcJsonData = cJSON_Parse(jsonData); if(!srcJsonData) { printf("Error:%s\r\n",cJSON_GetErrorPtr()); } else { cJSON *value; value = cJSON_GetObjectItem(srcJsonData,"name"); if(value->type == cJSON_String) { printf("书名:%s\r\n",value->valuestring); } value = cJSON_GetObjectItem(srcJsonData,"pages"); if(value->type == cJSON_Number) { printf("页数:%d\r\n",value->valueint); } cJSON_Delete(srcJsonData); } }
|
运行结果:
1 2 3 4 5 6
| 书名:C Primer pluse 页数:626
-------------------------------- Process exited after 0.01452 seconds with return value 0 请按任意键继续. . .
|
例子2
上面是一个最基本的测试程序,JSON数据也是直接通过C语言的字符串保存的。
实际的使用中,JSON数据的内容较为庞大,再使用C语言的字符串来保存,则会及其麻烦(想想那一堆反斜杠)。
所以,一般都是使用文件的形式来保存JSON数据。
准备一个原始数据用于测试,如下面的data.txt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| { "class":"C语言书籍", "books":[{ "name":"C Primer pluse", "author":"Stephen Prata", "publishing":"人民邮电出版社" }, { "name":"C程序设计", "author":"谭浩强", "publishing":"清华大学出版社" }, { "name":"C陷阱与缺陷", "author":"Andrew Koenig", "publishing":"人民邮电出版社" }] }
|
先来分析下这个JSON数据的结构:
- 最外面的大括号,表示这个一个JSON对象
- 对象里面有2个数据,key1是class,key2是books
- books的value又是一个中括号表示的数组
- 数组内又包含了3个对象,每个对象有3个数据,key1是name,key2是author,key3是publishing
解析这种JSON文件,使用要使用 fopen()
来打开这个文件:
1
| FILE *fp = fopen("data.txt", "r");
|
这里还要使用fseek()
和ftell()
来计算文件的大小,目的是用于后面的分配内存时指定大小。
然后使用fread()
将文件内存读入内存中分配的buf中:
1
| fread(buf, fileSize, sizeof(char), fp);
|
接着,还是使用cJSON_Parse()
将JSON数据解析为 cJSON
型的对象
1
| cJSON *srcJsonData = cJSON_Parse(buf);
|
然后就可以使用cJSON库中提供的各种函数来操作这个对象了。
这次会用到cJSON_GetObjectItem()
、cJSON_GetArrayItem()
、cJSON_GetArraySize()
、cJSON_Print()
等函数。
注意是使用完cJSON_Print()
后,要使用free()
来释放。
具体的测试程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| #include <stdio.h> #include <stdlib.h> #include <memory.h> #include "cJSON.h"
void main(void) { FILE *fp = fopen("data.txt", "r"); if(fp == NULL) { return; } int fileSize; fseek(fp, 0, SEEK_END); fileSize = ftell(fp); printf("fileSize: %d\r\n", fileSize); fseek(fp, 0, SEEK_SET); char *buf = (char *)malloc(fileSize * sizeof(char)); memset(buf, 0, fileSize); int ret = fread(buf, fileSize, sizeof(char), fp); if(ret == -1) { fclose(fp); return; } printf("%s\r\n",buf); fclose(fp); cJSON *srcJsonData = cJSON_Parse(buf); free(buf); if(srcJsonData == NULL) { printf("err\r\n"); return; } cJSON *value; value = cJSON_GetObjectItem(srcJsonData, "class"); if(value == NULL) { printf("GetObjectItem err\r\n"); cJSON_Delete(srcJsonData); return; } char *data = cJSON_Print(value); printf("class = %s\r\n",data); free(data); value = cJSON_GetObjectItem(srcJsonData, "books"); if(value == NULL) { printf("GetObjectItem err\r\n"); cJSON_Delete(srcJsonData); return; } int len = cJSON_GetArraySize(value); printf("books data: len=%d\r\n",len); int i = 0; for(i=0; i<len; i++) { cJSON *tmpValue = cJSON_GetArrayItem(value,i); cJSON *nameValue = cJSON_GetObjectItem(tmpValue,"name"); cJSON *authorValue = cJSON_GetObjectItem(tmpValue,"author"); cJSON *publishValue = cJSON_GetObjectItem(tmpValue,"publishing"); if(nameValue == NULL || authorValue == NULL || publishValue == NULL) { printf("GetObjectItem err\r\n"); cJSON_Delete(srcJsonData); return; } char *print1 = cJSON_Print(nameValue); char *print2 = cJSON_Print(authorValue); char *print3 = cJSON_Print(publishValue); printf("[%d] %s \t %s \t %s\r\n",i+1,print1,print2,print3); free(print1); free(print2); free(print3); } cJSON_Delete(srcJsonData); }
|
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| fileSize: 433 { "class":"C语言书籍", "books":[{ "name":"C Primer pluse", "author":"Stephen Prata", "publishing":"人民邮电出版社" },
{ "name":"C程序设计", "author":"谭浩强", "publishing":"清华大学出版社" },
{ "name":"C陷阱与缺陷", "author":"Andrew Koenig", "publishing":"人民邮电出版社" }] } class = "C语言书籍" books data: len=3 [1] "C Primer pluse" "Stephen Prata" "人民邮电出版社" [2] "C程序设计" "谭浩强" "清华大学出版社" [3] "C陷阱与缺陷" "Andrew Koenig" "人民邮电出版社"
-------------------------------- Process exited after 0.01578 seconds with return value 0 请按任意键继续. . .
|