简介
Jansson是一个用于解码、编码、操控JSON的C库。其特性为:
- 简单直观的API和数据模型
- 没有依赖项
- 完整的Unicode支持(UTF-8)
构建
Jansson使用cmake作为构建工具。可以执行下面的命令构建:
1
2
3
4
5
|
git clone https://github.com/akheron/jansson
cd jansson
mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX:STRING=/home/alex/CPP/lib/jansson/2.9 -DJANSSON_BUILD_DOCS=OFF ..
cmake --build . -- install
|
上述命令执行后,Jansson的头文件和静态库被安装到/home/alex/CPP/lib/jansson/2.9目录
使用
这里我们创建一个CMake工程:
1
2
3
4
5
6
7
|
cmake_minimum_required(VERSION 3.6)
project(jansson_demo C)
set(SOURCE_FILES main.c)
include_directories(/home/alex/CPP/lib/jansson/2.9/include)
add_executable(jansson_demo ${SOURCE_FILES})
set_property(TARGET jansson_demo PROPERTY C_STANDARD 99)
target_link_libraries(jansson_demo /home/alex/CPP/lib/jansson/2.9/lib/libjansson.a)
|
解码JSON
下面的代码展示了如何把字符串解码为json_t结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
#include
#include
int main() {
char *text = "{ \"name\":\"汪震\", \"age\":30, \"children\":[ \"彩彩\", \"当当\" ] }";
json_error_t error;
// json_t用于引用任何JSON节点
json_t *root = json_loads( text, 0, &error );
// 如果读取失败,自动置为空指针
if ( !root ) {
fprintf( stderr, "error: on line %d: %s\n", error.line, error.text );
return 1;
} else {
// json_is_*宏用于判断数据类型
// 处理JSON对象
assert( json_is_object( root ));
json_t *name, *age, *children;
name = json_object_get( root, "name" );
age = json_object_get( root, "age" );
fprintf( stdout, "NAME: %s, AGE: %d\n", json_string_value( name ), json_integer_value( age ));
children = json_object_get( root, "children" );
// 处理JSON数组
assert( json_is_array( children ));
int sof = json_array_size( children );
for ( int i = 0; i != sof; i++ ) {
json_t *child = json_array_get( children, i );
fprintf( stdout, "CHILDREN: %s\n", json_string_value( child ));
}
// 减小引用计数,导致资源回收
json_decref( root );
}
return 0;
}
|
运行上述代码后输出:
1
2
3
|
NAME: 汪震, AGE: 30
CHILDREN: 彩彩
CHILDREN: 当当
|
编码JSON
下面的代码展示了如何把json_t结构编码为字符串:
1
2
3
|
json_t *root = json_pack( "{sssis[ss]}", "name", "汪震", "age", 30, "children", "彩彩", "当当" );
char *text = json_dumps( root, JSON_INDENT( 4 ) | JSON_SORT_KEYS );
fprintf( stdout, "%s\n", text );
|
运行上述代码后输出:
1
2
3
4
5
6
7
8
|
{
"age": 30,
"children": [
"彩彩",
"当当"
],
"name": "汪震"
}
|
打包JSON
下面的代码展示了如何把零散数据打包(pack)为json_t结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
assert( json_is_integer( json_pack( "i", 1 )));
assert( json_is_array(
// jansson使用格式限定符来指定要创建的JSON的JSON节点的类型
// 下面的例子创建三元素的数组:字符串、字符串、布尔值
json_pack( "[ssb]", "foo", "bar", 1 )
));
/* 打包一个空对象 */
json_pack( "{}" );
/* 打包出 {age:30,childNum:2} */
json_pack( "{sisi}", "age", 30, "childNum", 2 );
/* 打包出 [[1, 2], {"num": true}] */
json_pack( "[[i,i],{s:b}]", 1, 2, "num", 1 );
return 0;
|
可用的格式限定符如下表:
限定符 | 说明 |
s | 将null结尾的UTF-8字符串转换为JSON字符串 |
s? | 和上面类似,但是如果位置参数是NULL则插入JSON null值 |
s# | 对应两个位置参数const char *, int,将指定长度的UTF-8缓冲转换为JSON字符串 |
s% | 和上面类似,只是未知参数类型为const char *, size_t |
+ | 把此位置参数连接到前一个位置参数后面 |
+# | 和上面类似,接收位置参数const char *, int |
+% | 和上面类似,接收位置参数const char *, size_t |
n | 输出null,不消耗位置参数 |
b | 转换int为JSON布尔值 |
i | 转换int为JSON整数 |
I | 转换json_int_t为JSON整数 |
f | 转换double为JSON实数 |
o | 原样插入json_t*结构 |
O | 和上面类似,但是目标json_t的引用计数会增加 |
o? o? | 类似上面两个,但是当位置参数为NULL时插入null |
[fmt] | 使用内部的格式限定符构建一个JSON数组,fmt可以是任意符合要求的格式限定符序列 |
{fmt} | 使用内部的格式限定符构建一个JSON对象,fmt可以是任意符合要求的格式限定符序列 |
解包JSON
下面的代码展示了如何把json_t结构解包为零散数据:
1
2
3
4
5
6
|
json_t *root = json_pack( "{sssis[ss]}", "name", "汪震", "age", 30, "children", "彩彩", "当当" );
char *name;
int age;
// 可以仅仅解包一部分
json_unpack( root, "{sssi}", "name", &name, "age", &age );
fprintf( stdout, "NAME: %s, AGE:%d\n", name, age );
|