linux C语言 libjson-c解析 JSON格式 生成JSON格式 API

本文档展示了如何在Linux环境下使用C语言生成和解析JSON格式的数据。通过示例代码,详细说明了如何构造JSON串行参数,并利用json-c库进行JSON数据的解析,包括提取JSON对象中的数组元素并转换为结构体。在解析过程中,注意了避免double free错误的问题。
摘要由CSDN通过智能技术生成

前言:在linux下C语言项目中经常会使用到JSON格式,记录一次JSON格式的生成和解析

生成JSON格式,项目用来下发串口参数

json-c官方API文档

	int index = 0;
	char buff[1024] = {0};
	index += sprintf(buff + index, "{\r\n");
	index += sprintf(buff + index, "\"serial_para\":\r\n");
	index += sprintf(buff + index, "[\r\n");
	index += sprintf(buff + index, "{\r\n");
	index += sprintf(buff + index, "\"device_name\":\"_/dev/ttyS3\",\r\n");
	index += sprintf(buff + index, "\"ip_addr\":\"10.20.1.83\",\r\n");
	index += sprintf(buff + index, "\"ip_port\":9333,\r\n");
	index += sprintf(buff + index, "\"speed\":115200,\r\n");
	index += sprintf(buff + index, "\"data_bit\":8,\r\n");
	index += sprintf(buff + index, "\"stop_bit\":1,\r\n");
	index += sprintf(buff + index, "\"parity\":\"N\"\r\n");
	index += sprintf(buff + index, "},\r\n");
	index += sprintf(buff + index, "{\r\n");
	index += sprintf(buff + index, "\"device_name\":\"_/dev/ttyS5\",\r\n");
	index += sprintf(buff + index, "\"ip_addr\":\"10.20.1.83\",\r\n");
	index += sprintf(buff + index, "\"ip_port\":9555,\r\n");
	index += sprintf(buff + index, "\"speed\":115200,\r\n");
	index += sprintf(buff + index, "\"data_bit\":8,\r\n");
	index += sprintf(buff + index, "\"stop_bit\":1,\r\n");
	index += sprintf(buff + index, "\"parity\":\"N\"\r\n");
	index += sprintf(buff + index, "}\r\n");
	index += sprintf(buff + index, "]\r\n");
	index += sprintf(buff + index, "}\r\n");
	//以上代码段生成JSON格式的buff如下
	
	{
		serial_para:
		[
			{
				"device_name":"_/dev/ttyS3",
				"ip_addr":"10.20.1.83",
				"ip_port":9333,
				"speed":115200,
				"data_bit":8,
				"stop_bit":1,
				"parity":"N"
			},
			{
				"device_name":"_/dev/ttyS5",
				"ip_addr":"10.20.1.83",
				"ip_port":9335,
				"speed":115200,
				"data_bit":8,
				"stop_bit":1,
				"parity":"N"
			}
		]
	}

解析JSON格式

struct serial_para {
	char dev_name[16];
	char ip_addr[16];
	int ip_port;
	int speed;
	int databit;
	int stopbit;
	char parity[32];
};

int handle_json_data(char *buff) {
	int i = 0;
	int ret = 0;
	size_t array_cnt;
	char tmp[32] = {0};
	char msg[128] = {0};
	json_object *obj, *sub_obj;
	struct serial_para serial_info;

	//serial_info = (struct serial_para *)malloc(sizeof(struct serial_para));
	obj = sub_obj = NULL; 
	const char *ok_msg = {"{\"status\":\"OK\"}"};
	const char *err_msg1 = {"{\"status\":\"Invalid JSON Format\"}"};	
	const char *err_msg2 = {"{\"status\":\"Invalid param\"}"};

	obj = json_tokener_parse(buff);  /* 检查是否为标准JSON格式错误返回 */
	if (obj == NULL) {
		strcpy(msg, err_msg1);
		log_info("client data Invalid JSON Format");
		return -1;
	}

	ret = json_object_object_get_ex(obj, "serial_para", &sub_obj); /* 从JSON格式中取出数组对象 */
	if (ret != 1) {
		log_info("Fails to get params");
		strcpy(msg, err_msg2);
		return -1;
	}

	enum json_type type = json_object_get_type(sub_obj);   /*判断对象JSON类型为数组*/

	if(type == json_type_array) {
		array_cnt = json_object_array_length(sub_obj);  /* 获取数据对象的个数这里返回2 */
		log_info("get json array success cnt = %d", array_cnt);	
	
		for(i = 0; i < array_cnt; i++) {
			json_object *array_obj = json_object_array_get_idx(sub_obj, i); /* 根据index循环获取单个数组对象 */
	
			get_json_string(array_obj, "device_name", tmp);  /* 在数组对象中取出各个key的value值 */
			strcpy(serial_info.dev_name, tmp);
			memset(tmp, 0, 32);
			
			get_json_string(array_obj, "ip_addr", tmp);
			strcpy(serial_info.ip_addr, tmp);
			memset(tmp, 0, 32);
			
			get_json_string(array_obj, "ip_port", tmp);
			serial_info.ip_port = atoi(tmp);
			memset(tmp, 0, 32);

			get_json_string(array_obj, "speed", tmp);
			serial_info.speed = atoi(tmp);
			memset(tmp, 0, 32);
			
			get_json_string(array_obj, "data_bit", tmp);
			serial_info.databit = atoi(tmp);
			memset(tmp, 0, 32);
			
			get_json_string(array_obj, "stop_bit", tmp);
			serial_info.stopbit = atoi(tmp);
			memset(tmp, 0, 32);
			
			get_json_string(array_obj, "parity", tmp);
			strcpy(serial_info.parity, tmp);
			memset(tmp, 0, 32);
			
			sys_serial2net(serial_info);
			memcpy(&serial_info_g[i], &serial_info, sizeof(struct serial_para));
			
			if (array_obj != NULL) {
				//json_object_put(array_obj);
			}
		}
	}
	
	if (obj != NULL) {
		//json_object_put(obj);
	}

	if (sub_obj != NULL) {
		//json_object_put(sub_obj);
	}
	
	strcpy(msg, ok_msg);
	return 0;
}

其中json_object_put全部注释掉了,因为发现任何一个json_object_put都会导致段错误,查看API文档后发现json_object_array_get_idx函数会释放这些变量的空间,当再次释放的时候就会导致double free的段错误。以下是官网API表述。

JSON_EXPORT int json_object_put ( 结构json_object * 对象 )
减少 json_object 的引用计数,如果达到零则释放。

在执行此操作之前,您必须拥有 obj 的所有权,否则会导致引用计数不平衡,从而导致经典的 use-after-free 错误。特别是,您通常不需要调用orjson_object_put()返回的 json_object 。json_object_object_get() 、json_object_array_get_idx()

就像在调用一块内存之后一样,在调用它或它所属的任何对象之后free(),你不能使用它(除非你知道你已经调用了显式增加引用计数)。objjson_object_put()json_object_get(obj)

NULL 可能会被传递,这种情况下这是一个空操作。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值