cJSON介绍及使用

2023-11-13

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  

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

cJSON介绍及使用 的相关文章

  • 使用 ChatGPT、Stable Diffusion、React 和 NodeJS 构建网站画廊

    TLDR 在本文中 您将学习如何构建一个 Web 应用程序 该应用程序使用 ChatGPT 和 Stable Diffusion 为您提供的任何网站描述生成徽标和合适的域名 介绍 人工智能正在接管世界 这些技术每天都在震撼着我们的世界 Ch
  • 家里用服务器放在哪个位置,路由器摆放在家中哪个位置好 路由器摆放位置【详解】...

    路由器摆放在家中哪个位置好 路由器的摆放位置其实非常讲究的 这里就给大家讲解下相关知识 一起来看看 其实wifi所发射的信号 也就是无线电波 向手机和收音机发射出的电磁波是一样的 但是呢wifi的信号相当的短 一般常见的话只有12公分左右
  • Windows Server 系列 - User logon name(pre-Windows 2000) 和 User logon name 的区别

    一 在Active Directory中一直疑惑User logon name pre Windows 2000 和 User logon name这两个字段的区别 详细如下 AD UI界面展示名称 AD 后端属性名称 User logon
  • 使用Composition API和setup语法糖重构Vue组件

    Vue3 引入了Composition API 它是一种更灵活的方式来组织和复用组件的逻辑 而不是依赖于传统的选项式API 如data methods computed等 Composition API的核心是一个名为setup的函数 它可
  • 如何在github上重命名或修改文件夹

    在github上整理流程的时候 有一个文件夹命名不合适 想返回去改 但是在网页上没有找到重命名文件夹的选项 经过一番折腾之后 我是这么做的 1 首先在服务器上找到公匙 公匙在 ssh目录下 以 pub结尾的文件 将其复制 2 在github
  • markdown基本用法

    标题 和 都可以用于表示标题 一级标题 二级标题 一级标题 二级标题 三级标题 四级标题 五级标题 六级标题 标题的前后都要空一行 号后应当加一个空格 和 应当顶格书写 建议使用 来表示标题 字体 斜体 斜体 加粗 粗体 斜体 加粗 斜体
  • OpenCV中的人脸活体检测和身份认证如何实现?OpenCV人脸识别

    本文将介绍如何在OpenCV中实现人脸活体检测和身份认证 结合人脸检测 关键点定位和深度学习模型 我们可以有效地检测和区分真实人脸和照片 视频等非真实生物特征 以实现可靠的身份认证和活体检测 人脸检测和关键点定位 使用OpenCV提供的人脸
  • [STM32学习笔记(一)] 如何安装keil5 MDK版本并安装C51

    文章目录 1 注意事项 2 安装流程 2 1 获取Keil5安装包 2 2 安装keil5 2 3破解keil5 MDK 2 4 安装STM32芯片包 3 在安装了mdk的基础上安装c51 1 注意事项 安装路径必须全部是英文 如果已经安装
  • 突破前端反调试:阻止页面无限不断debugger

    不知道你们有没有遇到过上图这样 有时候想调试网站 一打开开发者工具立即 debugger 而且跳过了还是会继续 或者是有时候在调试网页时 突然就给你来一个 debugger 接着就是反复来回 debugger 了 贼烦 那今天分享个教程 教
  • Spock1

    文章目录 背景 扩展 BDD Behavior driven development行为驱动测试 依赖 Demo Spock深入 结构 setup与given assert 异常断言 Mock 创建对象 注入对象 调用频率约束 目标约束 方
  • Nacos-2.1.1安装配置+集群

    Nacos安装配置 集群 nacos 2 1 1安装配置 集群 Linux 一 环境准备 二 Nacos安装 运行 单机 三 替换nacos内置数据源 四 nacos集群配置 nacos 2 1 1安装配置 集群 Linux 本篇博客用于记
  • linux 启动盘zhi,Linux制作启动盘之dd命令详解

    1 dd命令简介 dd在linux中是 一个非常强大的工具 常用于复制大量数据 测试读写性能 清空硬盘数据 不可恢复 由于dd 命令允许以二进制方式读写 所以特别适合在原始设备上输入 输出 dd命令用于复制文件并对原文件的内容进行转换和格式
  • Windows 通过CMD窗口利用mybatis-generator连接Oracle快速生成代码

    环境说明 Windows10 JDK8 ojdbc6 11 2 0 4 jar mybatis generator core 1 3 7 jar 1 在C盘新建autoMybatis文件夹 文件夹中新建generator xml文件 并将o
  • bzoj3309 DZY Loves Math

    题目链接 bzoj3309 题目大意 对于正整数n 定义f n 为n所含质因子的最大幂指数 给定正整数a b 求 ai 1 bj 1f gcd i j sum i 1 a sum j 1 b f gcd i j T lt 10000 1 l
  • Android系统中设置TextView的行间距

    Android系统中TextView默认显示中文时会比较紧凑 不是很美观 为了让每行保持一定的行间距 可以设置属性android lineSpacingExtra或android lineSpacingMultiplier 1 设置行间距

随机推荐

  • Echarts中X轴label间隔显示=>interval

    项目中我们经常都会遇到大量数据 需要我们的echarts来展示 但是我们的X轴的label是长度是有限的 在大量数据的传递下必然出现label重叠 这个时候我们就要用到interval如图 通过设置xAxis中的axisLabel inte
  • OpenMP和OpenACC

    OpenMP OpenMP是CPU的并行编程模型 它使用编译器指令来识别并行区域 omp set num threads n streams 用来指定要用到的CPU线程数 类似于设置环境变量 pragma omp parrallel 标记代
  • 使用openMVS对样例数据进行重建

    openMVS根据github上的步骤进行编译 注意 如果没有GPU 用不了CUDA的话 那么需要在openMVS目录下找到CmakeLists txt文件 把CUDA设置为OFF SET OpenMVS USE CUDA OFF CACH
  • linux系统之字符设备驱动——IIC驱动mma8451q

    linux系统之字符设备驱动 IIC子系统驱动mma8451q 1 原理图 2 驱动程序 mma8451q c Author your name Date 2021 02 23 22 16 37 LastEditTime 2021 02 2
  • The POM for is missing no dependency information available

    环境 win7 64 MyEclipse 10 5 java version 1 8 0 91 报错 1 导入报错 No marketplace entries found to handle maven compiler plugin 3
  • 求一个数阶乘末尾有几个零

    昨天校赛有一道题 是求一个数的阶乘 末尾有几个零 当时是没有做出来的 今天网上看了下 明白了原理 其实很多人都写过了 自己之所以再写 一是为了加强自己的理解 二是有的地方或许可以写得更详细 也写出自己思考的一些误区 回到题目本身 求一个数的
  • VTK库的编译和安装

    一 准备工具 CMake工具 Visual Studio 2013 VTK 8 1 0 The Visualization Toolkit 最新版源码 或者其他版本 二 使用CMake生成VTK的MS VS工程文件 打开CMake 设置源码
  • 基于CUDA的GPU优化建议

    l GPU硬件特性 n 存储层次 u Global memory l 大小一般为几GB l chip off的DRAM介质存储器 l 访问速度慢 是shared memory的上百倍 l 对于是否对齐和连续访问敏感 由DRAM的性质决定 l
  • 非常适合金融人的副业,不用坐班,时间自由!

    最近在论坛上看到一个测试 特扎心 以下三种情况 哪个让你最绝望 月薪4500 花呗欠了10000 被领导骂到哭 因为没钱不敢裸职 租房子的中介公司突然倒闭 房东逼你搬出去 你却拿不出押一付三的费用 说实话 我真的选不出 每一个都让我崩溃 0
  • 什么是白盒测试?什么是黑盒测试?两者的主要区别

    从测试方法上分 软件测试可分为白盒测试和黑盒测试 1 白盒测试 白盒测试 又称结构测试 主要用于单元测试阶段 它的前提是可以把程序看成装在一个透明的白箱子里 测试者完全知道程序的结构和处理算法 这种方法按照程序内部逻辑设计测试用例 检测程序
  • R语言—数据框

    文章目录 数据框 Dataframe 创建数据框 数据框的访问 通过组件的索引值来访问组件 通过组件的组件名来访问组件 通过访问矩阵的方式来访问组件 数据筛选 扩展数据框 添加列 添加行 使用apply 函数 数据框 Dataframe 数
  • 机器学习路径

    文章目录 前言 1 课前准备 2 主流的学习过程 3 具体内容 4 主要方向 体系 自然语言处理 知识图谱 计算机视觉 人机交互 参考资料 前言 1 机器学习到底应该怎么去学 机器学习的学习没有想象中的那么困难 当然也没有外面宣传的那么容易
  • R语言中的参数估计

    R语言中的参数估计 一直想要写博客来着 一直没有实现 昨天看室友写了 借着复习R语言考试 来开启我的第一篇博客叭 以下我将从点估计 区间估计来介绍区间估计 本文主要介绍R代码 具体的统计知识 详情可参考相关数理统计的专业书嗷 参数估计 R语
  • Day2 剑指offer

    30题 栈 定义栈的数据结构 请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中 调用 min push 及 pop 的时间复杂度都是 O 1 示例 MinStack minStack new MinStack minStac
  • 【0007】由于找不到MSVCR100.dll,无法继续执行代码

    下载安装Microsoft Visual C 2010 VC2010运行库 程序语言编译环境就能解决 官网下载地址 https www microsoft com zh CN download details aspx id 14632
  • 机器学习历程——人工智能基础与应用导论 专题篇(statsmodel)(3)

    目录 一 介绍 1 官网 2 主要功能 3 安装 二 t检验 1 概念 2 假设条件 3 单样本t检验 4 配对样本t检验 三 McNemar检验与Nemenyi检验 四 Friedman检验 一 介绍 1 官网 Introduction
  • Vue:统计代码行数

    1 在代码目录下打开git bash 2 在代码目录下打开git bash find name html or name js or name css or name vue print xargs wc l 运行结果 3 命令解析 fin
  • 中国银行业发展前景预测与未来战略规划建议报告2022-2028年版

    中国银行业发展前景预测与未来战略规划建议报告2022 2028年版 报告目录 第一章 2020 2022年国际银行业分析 1 1 2020 2022年全球银行业运行状况分析 1 1 1 全球宏观经济 1 1 2 金融市场波动 1 1 3 行
  • vue监听watch使用

    watch监听一定要监听 属性值 也就是data值 案例 data return language methods handleSetLanguage lang this i18n locale lang this language lan
  • cJSON介绍及使用

    JSON JavaScript Object Notation 是一种轻量级的文本数据交换格式 易于让人阅读 同时也易于机器解析和生成 尽管JSON是Javascript的一个子集 但JSON是独立于语言的文本格式 并且采用了类似于C语言家