jansson库使用

jansson库使用

1. 将结构体转化为json字符串(解决jansson转化字符串失败)

写了一个转换测试程序,发现运行个20多次后,就一直转换失败了。先后测试free(),json_object_clear() 和 json_decref()。发现只有json_decref()这个好使。估计是内存泄露导致的。

uint32_t mydata_oildrop_item_to_json(mydata_oildrop_item_t *item, char *buff, size_t len)
{
    JSON_NULL_PTR_ASSERT(item);

    json_t *root = NULL;
	char *out = NULL;
	size_t out_len = 0;
	
    root = json_pack("{s:i, s:i, s:i, s:i}", "effective", item->effective, "oil_drop_reason", item->oil_drop_reason, \
                                            "oil_drop_quantity", item->oil_drop_quantity, "timestamp", item->timestamp);
    if (root == NULL)
    {
        return NRF_ERROR_INVALID_DATA;
    }

    out = json_dumps(root, JSON_ENCODE_ANY);
	out_len = strlen(out);
	if (out_len >= len)
	{
		NRF_NUS_LOG_INFO("Buff is too small. Value: %d  Need: %d", len, out_len + 1);
		// free(root);
		// json_object_clear(root);
		json_decref(root);
		free(out);
		return NRF_ERROR_INVALID_LENGTH;
	}
	
	NRF_NUS_LOG_INFO("%s", buff);
	strncpy(buff, out, out_len);
    // free(root);
	// json_object_clear(root);
	json_decref(root);
	free(out);

    return NRF_SUCCESS;
}

在创建或者获取到一个json对象时,引用计数器会自增。我们在释放json对象所占用的内存时,需要通过json_decref()减小引用计数器的值,当引用计数器的值为0时,jansson库会释放掉json对象所占用的堆内存。

比如我通过json_object()创建一个json对象obj_1,然后通过json_array_append()将创建的这个对象0bj_1追加到另外一个json数组array_1中。当我们通过json_decref()释放掉数组对象array_1时,我们创建的json对象obj_1并不会被释放掉。

原因是:当我们使用json_array_append()时,obj_1的引用计数器会自增1,这个时候obj_1的引用计数器值为2,当我们释放掉array_1时,obj_1的引用计数器自减1,这个时候obj_1引用计数器值为1,obj_1占用的堆内存是没有释放掉的。反复进行这样的操作会导致,会导致堆内存泄露,最后没有办法申请内存,导致json库的API失败,或者导致程序跑飞。

另外,使用json_object_set_new(obj_1, obj_2)这类型的接口,是将对象obj_2添加到对象obj_1中,不是简单的指针赋值,而是重新创建,并且这个接口会使obj_2的引用计数器自减1,如果没有其它的json对象使用obj_2,即obj_2的引用计数器为1,则调用这个接口后,ojb_2空间将释放。

json_pack()接口转换失败。原因可能格式定义问题,比如我定义的格式是"{si,si}“,而我给的参数是(7,7),即json_pack(”{si,si}", 7, 7),这种情况会导致转换失败。

另外的,就是堆空间大小不够。比如我需要转化很大的一个json对象,此时是需要很大的内存的,堆内存小于需要的内存空间,也会导致转换失败。

    for (uint8_t i = 0; i < 10; i++)
    {
        ponit = json_pack("{s:[iiiiiiiiii],s:[iiiiiiiiii]}",
                          "temp", oil_drop_lines.lines[0].ponits[0].temp, oil_drop_lines.lines[0].ponits[1].temp,
                          oil_drop_lines.lines[0].ponits[2].temp, oil_drop_lines.lines[0].ponits[3].temp,
                          oil_drop_lines.lines[0].ponits[4].temp, oil_drop_lines.lines[0].ponits[5].temp,
                          oil_drop_lines.lines[0].ponits[6].temp, oil_drop_lines.lines[0].ponits[7].temp,
                          oil_drop_lines.lines[0].ponits[8].temp, oil_drop_lines.lines[0].ponits[9].temp,
                          "quanlity", oil_drop_lines.lines[0].ponits[0].quantity, oil_drop_lines.lines[0].ponits[1].quantity,
                          oil_drop_lines.lines[0].ponits[2].quantity, oil_drop_lines.lines[0].ponits[3].quantity,
                          oil_drop_lines.lines[0].ponits[4].quantity, oil_drop_lines.lines[0].ponits[5].quantity,
                          oil_drop_lines.lines[0].ponits[6].quantity, oil_drop_lines.lines[0].ponits[7].quantity,
                          oil_drop_lines.lines[0].ponits[8].quantity, oil_drop_lines.lines[0].ponits[9].quantity);

        if (ponit == NULL)
        {
            NRF_NUS_LOG_INFO("ponit null.");
            goto json_error;
        }

        line = json_pack("{si}", "oil_type", oil_drop_lines.lines[i].oil_type);
        if (line == NULL)
        {
            NRF_NUS_LOG_INFO("line null.");
            goto json_error;
        }

        ret = json_object_set(line, "ponits", ponit);

        if (ret != 0)
        {
            NRF_NUS_LOG_INFO("json_object_set_new.");
            goto json_error;
        }

        ret = json_array_append(lines, line);

        if (ret != 0)
        {
            NRF_NUS_LOG_INFO("json_array_append.");
            goto json_error;
        }

        json_decref(ponit);
        json_decref(line);
    }

此时,修改.s文件里面堆空间大小,让这个足够大即可。Nordic平台修改堆空间需要在如下窗口中设置。
在这里插入图片描述

posted @   duapple  阅读(38)  评论(0编辑  收藏  举报  
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!
点击右上角即可分享
微信分享提示