JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。简单来说就是一种文件格式,官方介绍。
JSON文件中只有两种结构:
其中value可以是字符串string,整型number,布尔型true,false,null,或者是对象object,数组array。但是JSON对象中的key值必须是字符串,而且不能重复。
JSON 对象
{
"name": "Jack (\"Bee\") Nimble",
"format": {
"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,
"frame rate": 24
}
}
JSON数组
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
[
[0, -1, 0],
[1, 0, 0],
[0, 0, 1]
]
cJSON是一个开源的JSON解析器,该项目包含了cJSON.c
和cJSON.h
两个文件。
cJSON官方下载网站:https://github.com/DaveGamble/cJSON
下载完成后无安装,只需要将cJSON.c
和cJSON.h
两个文件拷贝到项目的文件夹下即可。
使用下面命令编译一个使用cJSON的小例子:(解压的目录下有相关文件)
gcc cJSON.c test.c -o test -lm
./test
cJSON结构体的具体代码:
typedef struct cJSON {
struct cJSON *next,*prev;
struct cJSON *child;
int type;
char *valuestring;
int valueint;
double valuedouble;
char *string;
} cJSON;
cJSON默认所有值都为0,除非额外为其赋有意义的值。
next/prev是一个双向链表中的兄弟。next指向链表中下一个兄弟节点,prev指向本节点前一个节点。 只有对象和数组有child节点,并且child节点是双向链表的头节点。child的prev一般为NULL,不指向任何节点,而next一般是有指向的。 双向链表的最后一个兄弟节点的next是无指向的。
type取值如下:Null/True/False/Number/String/Array/Object。这些值类型都在cJSON.h中通过宏定义了。
Number类型节点有valueint和valuedouble。如果你想要整形值,读取valueint,否则读取valuedouble。
string表示节点的名称。所有的节点都是一个链表,都具有string值。
根据官网的demo,test.c文件,编写两个程序create_json.c
和read_json.c
,create_json.c
主要生成vedio.json
文件,然后read_json.c
再从vedio.json
中解析,并打印显示。
video.json
文件内容:
{
"name": "Jack (\"Bee\") Nimble",
"format": {
"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,
"frame rate": 24
},
"JSON arr1":["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
"JSON arr2":[[0, -1, 0], [1, 0, 0], [0, 0, 1]]
}
cJSON相关的函数解释可以参考这个cJSON的中文文档,链接在这里。
create_json.c
文件内容:
/******************************************************************************
* File: create_json.c
*
* Author: Seaworth
* Created: 03/07/20
* Description: 采用cJSON生成一个JSON格式的文件
*****************************************************************************/
#include
#include
#include
#include
#include
#include
#include "cJSON.h"
int main(int argc, char *argv[])
{
/* Our "Video" datatype: */
cJSON *root,*fmt;
root = cJSON_CreateObject();
cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject());
cJSON_AddStringToObject(fmt, "type", "rect");
cJSON_AddNumberToObject(fmt, "width", 1920);
cJSON_AddNumberToObject(fmt, "height", 1080);
cJSON_AddFalseToObject (fmt, "interlace");
cJSON_AddNumberToObject(fmt, "frame rate", 24);
// 添加一个JSON arrays到root
cJSON *arr1;
cJSON_AddItemToObject(root, "JSON arr1", arr1 = cJSON_CreateArray());
cJSON_AddItemToArray(arr1, cJSON_CreateString("Sunday"));
cJSON_AddItemToArray(arr1, cJSON_CreateString("Monday"));
cJSON_AddItemToArray(arr1, cJSON_CreateString("Tuesday"));
cJSON_AddItemToArray(arr1, cJSON_CreateString("Wednesday"));
cJSON_AddItemToArray(arr1, cJSON_CreateString("Thursday"));
cJSON_AddItemToArray(arr1, cJSON_CreateString("Friday"));
cJSON_AddItemToArray(arr1, cJSON_CreateString("Saturday"));
cJSON *arr2;
cJSON *arr2_1, *arr2_2, *arr2_3;
cJSON_AddItemToObject(root, "JSON arr2", arr2 = cJSON_CreateArray());
cJSON_AddItemToArray(arr2, arr2_1 = cJSON_CreateArray());
cJSON_AddItemToArray(arr2_1, cJSON_CreateNumber(0));
cJSON_AddItemToArray(arr2_1, cJSON_CreateNumber(-1));
cJSON_AddItemToArray(arr2_1, cJSON_CreateNumber(0));
cJSON_AddItemToArray(arr2, arr2_2 = cJSON_CreateArray());
cJSON_AddItemToArray(arr2_2, cJSON_CreateNumber(1));
cJSON_AddItemToArray(arr2_2, cJSON_CreateNumber(0));
cJSON_AddItemToArray(arr2_2, cJSON_CreateNumber(0));
cJSON_AddItemToArray(arr2, arr2_3 = cJSON_CreateArray());
cJSON_AddItemToArray(arr2_3, cJSON_CreateNumber(0));
cJSON_AddItemToArray(arr2_3, cJSON_CreateNumber(0));
cJSON_AddItemToArray(arr2_3, cJSON_CreateNumber(1));
// 将JSON数据转换为字符串,写入文件中
char* data = cJSON_Print(root);
printf("json:\n%s\n", data);
FILE* fp = fopen("video.json", "w");
fwrite(data, sizeof(char), strlen(data)+1, fp);
fclose(fp);
cJSON_Delete(root);
free(data);
return 0;
}
read_json.c
文件内容:
/******************************************************************************
* File: read_json.c
*
* Author: Seaworth
* Created: 03/07/20
* Description: 读取JSON格式的文件,对其进行解析
*****************************************************************************/
#include
#include
#include
#include
#include
#include
#include "cJSON.h"
// 定义结构体,方便后面解析数据,保存
typedef struct{
char type[32];
int width;
int height;
int interlace;
int frame_rate;
}format;
/* Parse text to JSON, then render back to text, and print! */
void doit(char *text)
{
char *out;cJSON *json;
json=cJSON_Parse(text);
if (!json) {printf("Error before: [%s]\n",cJSON_GetErrorPtr());}
else
{
out=cJSON_Print(json);
printf("print json:\n");
printf("%s\n",out);
}
printf("================================\n");
printf("parse json:\n");
cJSON *name=cJSON_GetObjectItem(json,"name");
if(name != NULL){
printf("name: %s\n", cJSON_Print(name));
}
cJSON *fmt=cJSON_GetObjectItem(json,"format");
if(fmt != NULL){
cJSON *item;
format f1;
item=cJSON_GetObjectItem(fmt,"type");
memcpy(f1.type,item->valuestring,strlen(item->valuestring));
item=cJSON_GetObjectItem(fmt,"width");
f1.width = item->valueint;
item=cJSON_GetObjectItem(fmt,"height");
f1.height = item->valueint;
item=cJSON_GetObjectItem(fmt,"interlace");
f1.interlace = item->valueint;
item=cJSON_GetObjectItem(fmt,"frame rate");
f1.frame_rate = item->valueint;
// 打印format的信息
printf("format: type=%s, width=%d, height=%d, interlace=%d, frame rate=%d\n",
f1.type, f1.width, f1.height, f1.interlace, f1.frame_rate);
}
cJSON *arr1=cJSON_GetObjectItem(json,"JSON arr1");
if(arr1 != NULL){
printf("JSON arr1:\n");
for (int i = 0; i < cJSON_GetArraySize(arr1); ++i) {
cJSON *node = cJSON_GetArrayItem(arr1, i);
printf("%s", node->valuestring);
if(i < cJSON_GetArraySize(arr1)-1){
printf(", ");
}
}
}
cJSON *arr2=cJSON_GetObjectItem(json,"JSON arr2");
if(arr2 != NULL){
printf("\nJSON arr2:\n");
for (int i = 0; i < cJSON_GetArraySize(arr2); ++i) {
cJSON *node1 = cJSON_GetArrayItem(arr2, i);
for (int j = 0; j < cJSON_GetArraySize(node1); ++j) {
cJSON *node2 = cJSON_GetArrayItem(node1, j);
printf("%d", node2->valueint);
if(j < cJSON_GetArraySize(node1)-1){
printf(", ");
}
}
printf("\n");
}
}
cJSON_Delete(json);
free(out);
}
/* Read a file, parse, render back, etc. */
void dofile(char *filename)
{
FILE *f;long len;char *data;
f=fopen(filename,"rb");fseek(f,0,SEEK_END);len=ftell(f);fseek(f,0,SEEK_SET);
data=(char*)malloc(len+1);fread(data,1,len,f);fclose(f);
doit(data);
free(data);
}
int main(int argc, char *argv[])
{
dofile("video.json");
return 0;
}
编译指令:
gcc cJSON.c create_json.c -o create_json -lm
gcc cJSON.c read_json.c -o read_json -lm
./create_json
./read_json
./read_json
的运行结果如下: