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平台修改堆空间需要在如下窗口中设置。