cJSON介绍及使用

JSON(JavaScript Object Notation)是一种轻量级的文本数据交换格式,易于让人阅读。同时也易于机器解析和生成。尽管JSON是Javascript的一个子集,但JSON是独立于语言的文本格式,并且采用了类似于C语言家族的一些习惯。JSON解析器和JSON库支持许多不同的编程语言。

几乎所有与网页开发相关的语言都有JSON库。JSON比XML更小、更快。

JSON用于描述数据结构,有以下形式存在:

(1)、对象(object):一个对象以”{“开始,并以”}”结束。一个对象包含一系列非排序的名称/值对,每个名称/值对之间使用”,”分隔。

(2)、名称/值(collection):名称和值之间使用”:”隔开。一个名称是一个字符串;一个值 (value)可以是双引号括起来的字符串(string)、数值(number)、true、false、null、对象(object)或者数组(array)。这些结构可以嵌套。

JSON语法规则:(1)、数据在键值对中;(2)、数据由逗号分隔;(3)、花括号保存对象;(4)、方括号保存数组。

JSON的值可以是:

(1)、数值:一系列0--9的数字组合,可以为负数或者小数。还可以用”e”或者”E”表示为指数形式。数值(number)也与C或者Java的数值非常相似。除去未曾使用的八进制与十六进制格式。除去一些编码细节。

(2)、字符串:以""括起来的一串字符。字符串(string)是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义。一个字符(character)即一个单独的字符串(character string)。字符串(string)与C或者Java的字符串非常相似。

(3)、布尔值:表示为true或者false。

(4)、数组(Array):数组是值(value)的有序集合。一个数组以”[“(左中括号)开始,”]”(右中括号)结束。值之间使用”,”(逗号)分隔。数组索引从0开始。

(5)、对象(object):对象是一个无序的”名称/值”对集合。一个对象以”{“开始,并以”}”结束。每个”名称”后跟一个”:”(冒号)。”名称/值”对之间使用”,”(逗号)分隔。

(6)、null:空白可以加入到任何符号之间。

各式各样开源的JSON库非常多,这里介绍下GitHub上DaveGamble的cJSON库的使用,地址: https://github.com/DaveGamble/cJSON  ,它用起来非常方便。

关于json11的使用可以参考:https://blog.csdn.net/fengbingchun/article/details/51396932

cJSON是一个仅有一个.h文件,一个.c文件组成的JSON解析器,它是由纯C(ANSI C89)实现的,跨平台性较好。cJSON中有一个cJSON结构体。cJSON是采用链表存储的。

以下是测试代码:

#include "funset.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"

#ifdef _MSC_VER
#include <Windows.h>
void utf8_to_gbk(const char* utf8, char* gbk)
{
	const int maxlen = 256;
	wchar_t unicode_str[maxlen];
	int outlen = MultiByteToWideChar(CP_UTF8, 0, utf8, strlen(utf8), unicode_str, maxlen);
	outlen = WideCharToMultiByte(CP_ACP, 0, unicode_str, outlen, gbk, 256, NULL, NULL);
	gbk[outlen] = '\0';
}
#else // linux
void utf8_to_gbk(const char* utf8, char* gbk)
{
	strcpy(gbk, utf8);
}
#endif

int read_file(const char* filename, char** content)
{
	// open in read binary mode
	FILE* file = fopen(filename, "rb");
	if (file == NULL) {
		fprintf(stderr, "read file fail: %s\n", filename);
		return -1;
	}

	// get the length
	fseek(file, 0, SEEK_END);
	long length = ftell(file);
	fseek(file, 0, SEEK_SET);

	// allocate content buffer
	*content = (char*)malloc((size_t)length + sizeof(""));

	// read the file into memory
	size_t read_chars = fread(*content, sizeof(char), (size_t)length, file);
	if ((long)read_chars != length) {
		fprintf(stderr, "length dismatch: %d, %d\n", read_chars, length);
		free(*content);
		return -1;
	}
	(*content)[read_chars] = '\0';

	fclose(file);
	return 0;
}

int test_cjson_1()
{
#ifdef __linux__
	const char* filename = "testdata/cjson_test7";
#else
	const char* filename = "E:/GitCode/Messy_Test/testdata/cjson_test7";
#endif
	char *json = NULL;
	if (read_file(filename, &json) != 0) return -1;;
	if ((json == NULL) || (json[0] == '\0') || (json[1] == '\0')) {
		fprintf(stderr, "file content is null\n");
		return -1;
	}

	cJSON* item = cJSON_Parse(json + 2);
	if (item == NULL) {
		fprintf(stderr, "pasre json file fail\n");
		return -1;
	}

	int do_format = 0;
	if (json[1] == 'f') do_format = 1;

	char *printed_json = NULL;
	if (json[0] == 'b') {
		// buffered printing
		printed_json = cJSON_PrintBuffered(item, 1, do_format);
	} else {
		// unbuffered printing
		if (do_format) printed_json = cJSON_Print(item);
		else printed_json = cJSON_PrintUnformatted(item);
	}

	if (printed_json == NULL) {
		fprintf(stderr, "print json fail\n");
		return -1;
	}
	printf("%s\n", printed_json);

	int num = cJSON_GetArraySize(item);
	for (int i = 0; i < num; ++i) {
		cJSON* arr = cJSON_GetArrayItem(item, i);
		if (arr == NULL) {
			fprintf(stderr, "get array item fail\n");
			return -1;
		}

		fprintf(stdout, "has item \"City\": %d; has item \"abc\": %d\n",
			cJSON_HasObjectItem(arr, "City"), cJSON_HasObjectItem(arr, "abc"));
		cJSON* tmp = cJSON_GetObjectItem(arr, "City");
		if (tmp != NULL)
			fprintf(stdout, "key: %s, value: %s\n", tmp->string, tmp->valuestring);
	}

	if (item != NULL) cJSON_Delete(item);
	if (json != NULL) free(json);
	if (printed_json != NULL) free(printed_json);

	return 0;
}

int test_cjson_2()
{
#ifdef __linux__
	const char* filename = "testdata/json.data";
#else
	const char* filename = "E:/GitCode/Messy_Test/testdata/json.data";
#endif
	char *json = NULL;
	if (read_file(filename, &json) != 0) return -1;;
	if ((json == NULL) || (json[0] == '\0') || (json[1] == '\0')) {
		fprintf(stderr, "file content is null\n");
		return -1;
	}

	cJSON* items = cJSON_Parse(json);
	if (items == NULL) {
		fprintf(stderr, "pasre json file fail\n");
		return -1;
	}

	char* printed_json = cJSON_PrintUnformatted(items);
	if (printed_json == NULL) {
		fprintf(stderr, "print json fail\n");
		return -1;
	}
	printf("%s\n\n", printed_json);

	cJSON*  item = cJSON_GetObjectItem(items, "name");
	fprintf(stdout, "key: %s, value: %s\n", "name", item->valuestring);

	char gbk[256];
	item = cJSON_GetObjectItem(items, "address");
	utf8_to_gbk(item->valuestring, gbk);
	fprintf(stdout, "key: %s, value: %s\n", "address", gbk);

	item = cJSON_GetObjectItem(items, "age");
	fprintf(stdout, "key: %s, value: %d\n", "age", item->valueint);

	item = cJSON_GetObjectItem(items, "value1");
	int size = cJSON_GetArraySize(item);
	for (int i = 0; i < size; ++i) {
		cJSON* tmp = cJSON_GetArrayItem(item, i);
		int len = cJSON_GetArraySize(tmp);
		fprintf(stdout, "key: %s:", "value1");
		for (int j = 0; j < len; ++j) {
			cJSON* tmp2 = cJSON_GetArrayItem(tmp, j);
			fprintf(stdout, " %f,", tmp2->valuedouble);
		}
		fprintf(stdout, "\n");
	}

	item = cJSON_GetObjectItem(items, "value2");
	size = cJSON_GetArraySize(item);
	fprintf(stdout, "key: %s:", "value2");
	for (int i = 0; i < size; ++i) {
		cJSON* tmp = cJSON_GetArrayItem(item, i);
		fprintf(stdout, " %f,", tmp->valuedouble);
	}
	fprintf(stdout, "\n");

	item = cJSON_GetObjectItem(items, "bei_jing");
	cJSON* tmp = cJSON_GetObjectItem(item, "address");
	utf8_to_gbk(tmp->valuestring, gbk);
	fprintf(stdout, "key: %s, value: %s\n", "address", gbk);
	tmp = cJSON_GetObjectItem(item, "car");
	fprintf(stdout, "key: %s, value: %d\n", "car", tmp->valueint);
	tmp = cJSON_GetObjectItem(item, "cat");
	fprintf(stdout, "key: %s, value: %d\n", "cat", tmp->valueint);

	item = cJSON_GetObjectItem(items, "shan_dong");
	tmp = cJSON_GetObjectItem(item, "address");
	utf8_to_gbk(tmp->valuestring, gbk);
	fprintf(stdout, "key: %s, value: %s\n", "address", gbk);
	tmp = cJSON_GetObjectItem(item, "value1");
	size = cJSON_GetArraySize(tmp);
	for (int i = 0; i < size; ++i) {
		char* names[2] = { "ji_nan", "tai_an" };
		cJSON* tmp2 = cJSON_GetArrayItem(tmp, i);
		cJSON* tmp3 = cJSON_GetObjectItem(tmp2, names[i]);
		utf8_to_gbk(tmp3->valuestring, gbk);
		fprintf(stdout, "key: %s, value: %s\n",names[i], gbk);
	}

	if (items != NULL) cJSON_Delete(items);
	if (json != NULL) free(json);
	if (printed_json != NULL) free(printed_json);

	return 0;
}

其中test_cjson_2()函数是解析如下json的测试代码:

{
  "name": "spring",
  "address": "北京",
  "age": 30,
  "value1": [[23, 43, -2.3, 6.7, 90],
             [-9, -19, 10, 2],
             [-5, -55]],
  "value2": [13.3, 1.9, 2.10],
  
  "bei_jing": {
    "address": "海淀",
    "car": false,
    "cat": true
  },
  "shan_dong": {
    "address": "济南",
    "value1": [{"ji_nan": "趵突泉"}, {"tai_an": "泰山"}]
  }
}

程序执行结果如下:

GitHubhttps://github.com/fengbingchun/Messy_Test  

猜你喜欢

转载自blog.csdn.net/fengbingchun/article/details/81606432