介绍

Jansson是一个对json格式进行编码,解码,操作的c语言库,有以下特点

  • 简单的api设计
  • 文档详尽
  • 无其他依赖库
  • 完全支持UTF-8
  • 大量的测试用例

Jansson是MIT license源码发布方式

Jansson支持多个平台,包括Unix以及windows

编译安装

解压并编译

tar -xvf jansson-2.4.tar.gz
./configure 
make
make check
make install

简单使用

只需要包含一个头文件

#include <jansson.h>

直接连接库方式编译

gcc -o prog prog.c -ljansson

或者利用pkg-config

gcc -o prog prog.c `pkg-config --cflags --libs jasson`

类型以及接口介绍

类型

Jasson主要使用的类型为

json_t

enum json_type
JSON_OBJECT
JSON_ARRAY
JSON_STRING
JSON_INTEGER
JSON_REAL
JSON_TRUE
JSON_FALSE
JSON_NULL

int json_typeof(const json_t *json)

json_is_object(const json_t *json)
json_is_array(const json_t *json)
json_is_string(const json_t *json)
json_is_integer(const json_t *json)
json_is_real(const json_t *json)
json_is_true(const json_t *json)
json_is_false(const json_t *json)
json_is_null(const json_t *json)

引用计数

Jasson利用引用计数管理内存,下面两个接口进行引用计数的增加和减少

json_t *json_incref(json_t *json)
void json_decref(json_t *json)

一般的操作是不会引起引用计数的变化的,需要人工进行增减,但是对于以_new 或者 _new_结束的可以自动对引用计数进行增减。

其他接口信息参见API Reference

例子

根据jansson-example摘抄如下
jansson.c

#include <stdio.h>
#include <string.h>
#include <jansson.h>

int main(void) {
  char* s = NULL;
  json_t *root = json_object();
  json_t *json_arr = json_array();
  
  json_object_set_new( root, "destID", json_integer( 1 ) );
  json_object_set_new( root, "command", json_string("enable") );
  json_object_set_new( root, "respond", json_integer( 0 ));
  json_object_set_new( root, "data", json_arr );
  json_array_append( json_arr, json_integer(11) );
  json_array_append( json_arr, json_integer(12) );
  json_array_append( json_arr, json_integer(14) );
  json_array_append( json_arr, json_integer(9) );
  s = json_dumps(root, 0);

  puts(s);
  json_decref(root);
  
  return 0;
}

使用gcc -g -o jansson jansson.c -ljansson,然后运行结果:

{"destID": 1, "command": "enable", "respond": 0, "data": [11, 12, 14, 9]}

如果你看到这里觉得结果输出没问题,按照上面的使用,可就捅了大篓子了,特别是针对频繁操作json的情况,看下执行valgrind后的结果:

[root jansson]#valgrind --leak-check=full ./jansson
==16417== Memcheck, a memory error detector
==16417== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16417== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==16417== Command: ./jansson
==16417==
{"destID": 1, "command": "enable", "respond": 0, "data": [11, 12, 14, 9]}
==16417==
==16417== HEAP SUMMARY:
==16417==     in use at exit: 170 bytes in 5 blocks
==16417==   total heap usage: 21 allocs, 16 frees, 1,037 bytes allocated
==16417==
==16417== 24 bytes in 1 blocks are definitely lost in loss record 1 of 5
==16417==    at 0x4C29E63: malloc (vg_replace_malloc.c:309)
==16417==    by 0x4E3F77D: json_integer (in /usr/lib64/libjansson.so.4.10.0)
==16417==    by 0x4008FE: main (jansson.c:14)
==16417==
==16417== 24 bytes in 1 blocks are definitely lost in loss record 2 of 5
==16417==    at 0x4C29E63: malloc (vg_replace_malloc.c:309)
==16417==    by 0x4E3F77D: json_integer (in /usr/lib64/libjansson.so.4.10.0)
==16417==    by 0x40091A: main (jansson.c:15)
==16417==
==16417== 24 bytes in 1 blocks are definitely lost in loss record 3 of 5
==16417==    at 0x4C29E63: malloc (vg_replace_malloc.c:309)
==16417==    by 0x4E3F77D: json_integer (in /usr/lib64/libjansson.so.4.10.0)
==16417==    by 0x400936: main (jansson.c:16)
==16417==
==16417== 24 bytes in 1 blocks are definitely lost in loss record 4 of 5
==16417==    at 0x4C29E63: malloc (vg_replace_malloc.c:309)
==16417==    by 0x4E3F77D: json_integer (in /usr/lib64/libjansson.so.4.10.0)
==16417==    by 0x400952: main (jansson.c:17)
==16417==
==16417== 74 bytes in 1 blocks are definitely lost in loss record 5 of 5
==16417==    at 0x4C29E63: malloc (vg_replace_malloc.c:309)
==16417==    by 0x4E3CC44: ??? (in /usr/lib64/libjansson.so.4.10.0)
==16417==    by 0x4E3A107: json_dumps (in /usr/lib64/libjansson.so.4.10.0)
==16417==    by 0x400975: main (jansson.c:18)
==16417==
==16417== LEAK SUMMARY:
==16417==    definitely lost: 170 bytes in 5 blocks
==16417==    indirectly lost: 0 bytes in 0 blocks
==16417==      possibly lost: 0 bytes in 0 blocks
==16417==    still reachable: 0 bytes in 0 blocks
==16417==         suppressed: 0 bytes in 0 blocks
==16417==
==16417== For lists of detected and suppressed errors, rerun with: -s
==16417== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 0 from 0)

存在内存泄露,正确的代码如下:

#include <stdio.h>
#include <string.h>
#include <jansson.h>

int main(void) {

  char* s = NULL;

  json_t *root = json_object();
  json_t *json_arr = json_array();

  json_object_set_new( root, "destID", json_integer( 1 ) );
  json_object_set_new( root, "command", json_string("enable") );
  json_object_set_new( root, "respond", json_integer( 0 ));
  json_object_set_new( root, "data", json_arr );

  json_array_append_new( json_arr, json_integer(11) );
  json_array_append_new( json_arr, json_integer(12) );
  json_array_append_new( json_arr, json_integer(14) );
  json_array_append_new( json_arr, json_integer(9) );

  s = json_dumps(root, 0);

  puts(s);
  json_decref(root);

  if(s)
  {
     free(s);
  }
 return 0;
}

解释如下:json_dumps函数里存在malloc,因此需要通过free释放内存。
json_array_append与json_array_append_new的区别是:

int json_array_append(json_t *array, json_t *value)
{
    return json_array_append_new(array, json_incref(value));
}

json_array_append对第二个参数传进来的json_t增加了引用,因此原结构没有释放。
修改后的代码通过valgrind执行结果:

[root jansson]#valgrind --leak-check=full ./jansson
==14943== Memcheck, a memory error detector
==14943== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14943== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==14943== Command: ./jansson
==14943==
{"destID": 1, "command": "enable", "respond": 0, "data": [11, 12, 14, 9]}
==14943==
==14943== HEAP SUMMARY:
==14943==     in use at exit: 0 bytes in 0 blocks
==14943==   total heap usage: 21 allocs, 21 frees, 1,037 bytes allocated
==14943==
==14943== All heap blocks were freed -- no leaks are possible
==14943==
==14943== For lists of detected and suppressed errors, rerun with: -s
==14943== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)