JSON格式學習和cJSON解析的基本操作

一、JSON是什麼?

JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。 易於人閱讀和編寫。同時也易於機器解析和生成。簡單來說就是一種文件格式,官方介紹

JSON文件中只有兩種結構:

  • 對象(object),也就是鍵值對,形式如{ “key1”: value1, “key2”: value2}
  • 數組(array),形式如[value1, value2, value3]

其中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開源庫的安裝

cJSON是一個開源的JSON解析器,該項目包含了cJSON.ccJSON.h兩個文件。

cJSON官方下載網站:https://github.com/DaveGamble/cJSON

下載完成後無安裝,只需要將cJSON.ccJSON.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值。

三、cJSON的基本操作

根據官網的demo,test.c文件,編寫兩個程序create_json.cread_json.ccreate_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 <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#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 <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>

#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的運行結果如下:

在這裏插入圖片描述

四、參考

  1. cJSON項目
  2. cJSON官方文檔翻譯
  3. JSON簡介
  4. 使用cJSON解析JSON字符串
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章