使用Jansson处理JSON
简介
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 <jansson.h> #include <assert.h> 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 ); |
Leave a Reply